From 6e84f7d153378b0ddbf6251142d71a73ec1a37b1 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 29 Oct 2022 21:14:02 +0800 Subject: [PATCH 1/8] Fix #103320, add explanatory message for [#must_use] --- .../locales/en-US/borrowck.ftl | 2 +- .../locales/en-US/lint.ftl | 1 + compiler/rustc_lint/src/lints.rs | 18 +++++ compiler/rustc_lint/src/unused.rs | 18 ++++- library/core/src/ops/arith.rs | 18 +++-- .../lint/unused/issue-103320-must-use-ops.rs | 27 ++++++++ .../unused/issue-103320-must-use-ops.stderr | 67 +++++++++++++++++++ 7 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 tests/ui/lint/unused/issue-103320-must-use-ops.rs create mode 100644 tests/ui/lint/unused/issue-103320-must-use-ops.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 0021638c10268..fe77cf23e8f94 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -33,7 +33,7 @@ borrowck_var_here_defined = variable defined here borrowck_var_here_captured = variable captured here -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure +borrowck_closure_inferred_mut = inferred to be a `FnMut` closure borrowck_returned_closure_escaped = returns a closure that contains a reference to a captured variable, which then escapes the closure body diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index dca678dff7a79..b1e7cc69a809b 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -309,6 +309,7 @@ lint_unused_generator = .note = generators are lazy and do nothing unless resumed lint_unused_def = unused {$pre}`{$def}`{$post} that must be used + .suggestion = use `let _ = ...` to ignore the resulting value lint_path_statement_drop = path statement drops value .suggestion = use `drop` to clarify the intent diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0c1019545f382..2e447b900e117 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1402,6 +1402,21 @@ pub struct UnusedDef<'a, 'b> { pub cx: &'a LateContext<'b>, pub def_id: DefId, pub note: Option, + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +pub enum UnusedDefSuggestion { + #[suggestion( + suggestion, + style = "verbose", + code = "let _ = ", + applicability = "machine-applicable" + )] + Default { + #[primary_span] + span: Span, + }, } // Needed because of def_path_str @@ -1417,6 +1432,9 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { if let Some(note) = self.note { diag.note(note.as_str()); } + if let Some(sugg) = self.suggestion { + diag.subdiagnostic(sugg); + } diag } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 4c9b3df2dbd33..622601224ff92 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,7 +1,7 @@ use crate::lints::{ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, - UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion, - UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, + UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim, + UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, }; use crate::Lint; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -418,6 +418,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { + let suggestion = if matches!( + cx.tcx.get_diagnostic_name(*def_id), + Some(sym::add) + | Some(sym::sub) + | Some(sym::mul) + | Some(sym::div) + | Some(sym::rem) + | Some(sym::neg), + ) { + Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() }) + } else { + None + }; cx.emit_spanned_lint( UNUSED_MUST_USE, *span, @@ -427,6 +440,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, + suggestion, }, ); } diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 75c52d3ecfc8b..fbf80d9f5a5af 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -86,7 +86,8 @@ pub trait Add { /// ``` /// assert_eq!(12 + 1, 13); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "add"] #[stable(feature = "rust1", since = "1.0.0")] fn add(self, rhs: Rhs) -> Self::Output; } @@ -195,7 +196,8 @@ pub trait Sub { /// ``` /// assert_eq!(12 - 1, 11); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "sub"] #[stable(feature = "rust1", since = "1.0.0")] fn sub(self, rhs: Rhs) -> Self::Output; } @@ -325,7 +327,8 @@ pub trait Mul { /// ``` /// assert_eq!(12 * 2, 24); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "mul"] #[stable(feature = "rust1", since = "1.0.0")] fn mul(self, rhs: Rhs) -> Self::Output; } @@ -459,7 +462,8 @@ pub trait Div { /// ``` /// assert_eq!(12 / 2, 6); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "div"] #[stable(feature = "rust1", since = "1.0.0")] fn div(self, rhs: Rhs) -> Self::Output; } @@ -562,7 +566,8 @@ pub trait Rem { /// ``` /// assert_eq!(12 % 10, 2); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "rem"] #[stable(feature = "rust1", since = "1.0.0")] fn rem(self, rhs: Rhs) -> Self::Output; } @@ -678,7 +683,8 @@ pub trait Neg { /// let x: i32 = 12; /// assert_eq!(-x, -12); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "neg"] #[stable(feature = "rust1", since = "1.0.0")] fn neg(self) -> Self::Output; } diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.rs b/tests/ui/lint/unused/issue-103320-must-use-ops.rs new file mode 100644 index 0000000000000..597d312fa5ecb --- /dev/null +++ b/tests/ui/lint/unused/issue-103320-must-use-ops.rs @@ -0,0 +1,27 @@ +// check-pass + +#![warn(unused_must_use)] +#![feature(never_type)] + +use std::ops::Add; +use std::ops::Sub; +use std::ops::Mul; +use std::ops::Div; +use std::ops::Rem; + +fn main() { + let x = 2_u32; + (x.add(4), x.sub(4), x.mul(4), x.div(4), x.rem(4)); + + x.add(4); //~ WARN unused return value of `add` that must be used + + x.sub(4); //~ WARN unused return value of `sub` that must be used + + x.mul(4); //~ WARN unused return value of `mul` that must be used + + x.div(4); //~ WARN unused return value of `div` that must be used + + x.rem(4); //~ WARN unused return value of `rem` that must be used + + println!("{}", x); +} diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.stderr b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr new file mode 100644 index 0000000000000..57439ec6a8fdb --- /dev/null +++ b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr @@ -0,0 +1,67 @@ +warning: unused return value of `add` that must be used + --> $DIR/issue-103320-must-use-ops.rs:16:5 + | +LL | x.add(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +note: the lint level is defined here + --> $DIR/issue-103320-must-use-ops.rs:3:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.add(4); + | +++++++ + +warning: unused return value of `sub` that must be used + --> $DIR/issue-103320-must-use-ops.rs:18:5 + | +LL | x.sub(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.sub(4); + | +++++++ + +warning: unused return value of `mul` that must be used + --> $DIR/issue-103320-must-use-ops.rs:20:5 + | +LL | x.mul(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.mul(4); + | +++++++ + +warning: unused return value of `div` that must be used + --> $DIR/issue-103320-must-use-ops.rs:22:5 + | +LL | x.div(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.div(4); + | +++++++ + +warning: unused return value of `rem` that must be used + --> $DIR/issue-103320-must-use-ops.rs:24:5 + | +LL | x.rem(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.rem(4); + | +++++++ + +warning: 5 warnings emitted + From 679dde7338281f958094b409202cc23ce1ba640c Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Feb 2023 05:55:48 +0000 Subject: [PATCH 2/8] fix parser mistaking const closures for const item --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 21 ++++++++++++++----- tests/ui/parser/recover-quantified-closure.rs | 2 +- .../parser/recover-quantified-closure.stderr | 4 ++-- .../const-closure-parse-not-item.rs | 10 +++++++++ 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index dcc3059a7f44c..701a2a3efcf2a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2108,7 +2108,7 @@ impl<'a> Parser<'a> { ClosureBinder::NotPresent }; - let constness = self.parse_constness(Case::Sensitive); + let constness = self.parse_closure_constness(Case::Sensitive); let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ffb23b50a160d..bb06ad20118d4 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -739,9 +739,10 @@ impl<'a> Parser<'a> { fn check_const_closure(&self) -> bool { self.is_keyword_ahead(0, &[kw::Const]) && self.look_ahead(1, |t| match &t.kind { - token::Ident(kw::Move | kw::Static | kw::Async, _) - | token::OrOr - | token::BinOp(token::Or) => true, + // async closures do not work with const closures, so we do not parse that here. + token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => { + true + } _ => false, }) } @@ -1203,8 +1204,18 @@ impl<'a> Parser<'a> { /// Parses constness: `const` or nothing. fn parse_constness(&mut self, case: Case) -> Const { - // Avoid const blocks to be parsed as const items - if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) + self.parse_constness_(case, false) + } + + /// Parses constness for closures + fn parse_closure_constness(&mut self, case: Case) -> Const { + self.parse_constness_(case, true) + } + + fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const { + // Avoid const blocks and const closures to be parsed as const items + if (self.check_const_closure() == is_closure) + && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) && self.eat_keyword_case(kw::Const, case) { Const::Yes(self.prev_token.uninterpolated_span()) diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs index df22f5e065c8f..10af39b700748 100644 --- a/tests/ui/parser/recover-quantified-closure.rs +++ b/tests/ui/parser/recover-quantified-closure.rs @@ -7,6 +7,6 @@ fn main() { enum Foo { Bar } fn foo(x: impl Iterator) { for ::Bar in x {} - //~^ ERROR expected one of `const`, `move`, `static`, `|` + //~^ ERROR expected one of `move`, `static`, `|` //~^^ ERROR `for<...>` binders for closures are experimental } diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr index 9ec4d2c034d0f..39eec80f658ad 100644 --- a/tests/ui/parser/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -1,8 +1,8 @@ -error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::` +error: expected one of `move`, `static`, `|`, or `||`, found `::` --> $DIR/recover-quantified-closure.rs:9:14 | LL | for ::Bar in x {} - | ^^ expected one of `const`, `move`, `static`, `|`, or `||` + | ^^ expected one of `move`, `static`, `|`, or `||` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/recover-quantified-closure.rs:2:5 diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs new file mode 100644 index 0000000000000..2c99d8bf1c677 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_trait_impl, const_closures)] +#![allow(incomplete_features)] + +const fn test() -> impl ~const Fn() { + const move || {} +} + +fn main() {} From f4e0ea7ad0c0cf88bf6fe04abe98471c423e9787 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Feb 2023 05:56:04 +0000 Subject: [PATCH 3/8] Replace `ConstFnMutClosure` with const closures --- library/core/src/cmp.rs | 13 +--- library/core/src/const_closure.rs | 78 ------------------- .../core/src/iter/adapters/array_chunks.rs | 6 +- .../core/src/iter/adapters/by_ref_sized.rs | 19 ++--- library/core/src/iter/mod.rs | 6 +- library/core/src/lib.rs | 2 - library/core/src/ops/try_trait.rs | 17 ++-- library/core/src/option.rs | 3 +- 8 files changed, 23 insertions(+), 121 deletions(-) delete mode 100644 library/core/src/const_closure.rs diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b75ae996e4853..f290e5baf9dd3 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,7 +22,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; use self::Ordering::*; @@ -1291,17 +1290,7 @@ where F: ~const Destruct, K: ~const Destruct, { - const fn imp K, K: ~const Ord>( - f: &mut F, - (v1, v2): (&T, &T), - ) -> Ordering - where - T: ~const Destruct, - K: ~const Destruct, - { - f(v1).cmp(&f(v2)) - } - max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) + max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2))) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs deleted file mode 100644 index 97900a4862f56..0000000000000 --- a/library/core/src/const_closure.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::marker::Destruct; -use crate::marker::Tuple; - -/// Struct representing a closure with mutably borrowed data. -/// -/// Example: -/// ```no_build -/// #![feature(const_mut_refs)] -/// use crate::const_closure::ConstFnMutClosure; -/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 { -/// *state += arg; -/// *state -/// } -/// let mut i = 5; -/// let mut cl = ConstFnMutClosure::new(&mut i, imp); -/// -/// assert!(7 == cl(2)); -/// assert!(8 == cl(1)); -/// ``` -pub(crate) struct ConstFnMutClosure { - /// The Data captured by the Closure. - /// Must be either a (mutable) reference or a tuple of (mutable) references. - pub data: CapturedData, - /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn - pub func: Function, -} -impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> { - /// Function for creating a new closure. - /// - /// `data` is the a mutable borrow of data that is captured from the environment. - /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually. - /// - /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure - /// and return the return value of the closure. - pub(crate) const fn new( - data: &'a mut CapturedData, - func: Function, - ) -> Self - where - Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, - { - Self { data, func } - } -} - -macro_rules! impl_fn_mut_tuple { - ($($var:ident)*) => { - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct, - { - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } - } - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, - { - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - #[allow(non_snake_case)] - let ($($var),*) = &mut self.data; - (self.func)(($($var),*), args) - } - } - }; -} -impl_fn_mut_tuple!(A); -impl_fn_mut_tuple!(A B); -impl_fn_mut_tuple!(A B C); -impl_fn_mut_tuple!(A B C D); -impl_fn_mut_tuple!(A B C D E); diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 5e4211058aa6f..af786609757b1 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,5 +1,4 @@ use crate::array; -use crate::const_closure::ConstFnMutClosure; use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce}; use crate::mem::{self, MaybeUninit}; use crate::ops::{ControlFlow, NeverShortCircuit, Try}; @@ -189,13 +188,12 @@ where I: Iterator, { #[inline] - default fn fold(mut self, init: B, mut f: F) -> B + default fn fold(mut self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp); - self.try_fold(init, fold).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 1945e402ff50e..477e7117c3ea1 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,7 +1,4 @@ -use crate::{ - const_closure::ConstFnMutClosure, - ops::{NeverShortCircuit, Try}, -}; +use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -39,13 +36,12 @@ impl Iterator for ByRefSized<'_, I> { } #[inline] - fn fold(self, init: B, mut f: F) -> B + fn fold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) - .0 + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -76,17 +72,12 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn rfold(self, init: B, mut f: F) -> B + fn rfold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold( - self.0, - init, - ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp), - ) - .0 + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index bb35d50b4bfda..00f57fbcc6162 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -362,15 +362,13 @@ macro_rules! impl_fold_via_try_fold { }; (@internal $fold:ident -> $try_fold:ident) => { #[inline] - fn $fold(mut self, init: AAA, mut fold: FFF) -> AAA + fn $fold(mut self, init: AAA, fold: FFF) -> AAA where FFF: FnMut(AAA, Self::Item) -> AAA, { - use crate::const_closure::ConstFnMutClosure; use crate::ops::NeverShortCircuit; - let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp); - self.$try_fold(init, fold).0 + self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 } }; } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 8961ef4ab4816..dc0702c467a4e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -376,8 +376,6 @@ mod bool; mod tuple; mod unit; -mod const_closure; - #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 84a69046807c4..9108fc6304525 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -379,13 +379,18 @@ pub(crate) type ChangeOutputType = <::Residual as Residual>:: pub(crate) struct NeverShortCircuit(pub T); impl NeverShortCircuit { - /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`. #[inline] - pub const fn wrap_mut_2_imp T>( - f: &mut F, - (a, b): (A, B), - ) -> NeverShortCircuit { - NeverShortCircuit(f(a, b)) + pub fn wrap_mut_2( + mut f: impl ~const FnMut(A, B) -> T, + ) -> impl ~const FnMut(A, B) -> Self { + cfg_if! { + if #[cfg(bootstrap)] { + #[allow(unused_parens)] + (const move |a, b| NeverShortCircuit(f(a, b))) + } else { + const move |a, b| NeverShortCircuit(f(a, b)) + } + } } } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c43b728022d2f..669fb475f1b8b 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1969,7 +1969,8 @@ impl const Default for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Option { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for Option { type Item = T; type IntoIter = IntoIter; From 3a75f10af12e959273d19cf0f867f066e3db8add Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Tue, 31 Jan 2023 12:09:54 +0100 Subject: [PATCH 4/8] Improve pretty-printing of `HirIdValidator` errors This now uses `node_to_string` for both missing and seen Ids, which includes the snippet of code for which the Id was allocated. Also removes the duplicated printing of `HirId`, as `node_to_string` includes that already. Similarly, changes all other users of `node_to_string` that do so, and changes the output of `node_to_string`, which is now "$hirid ($what `$span` in $path)". --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- .../src/mem_categorization.rs | 3 +- compiler/rustc_middle/src/hir/map/mod.rs | 27 ++++++------- compiler/rustc_middle/src/ty/context.rs | 2 +- .../rustc_middle/src/ty/typeck_results.rs | 5 +-- compiler/rustc_passes/src/hir_id_validator.rs | 39 +++++++------------ .../src/traits/error_reporting/suggestions.rs | 2 +- 7 files changed, 32 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a355a54d6959a..237142acca660 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -454,8 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e), None => { bug!( - "no type for node {}: {} in fcx {}", - id, + "no type for node {} in fcx {}", self.tcx.hir().node_to_string(id), self.tag() ); diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 48c75cde9a5fc..92240b66eb1d4 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -155,8 +155,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { None if self.is_tainted_by_errors() => Err(()), None => { bug!( - "no type for node {}: {} in mem_categorization", - id, + "no type for node {} in mem_categorization", self.tcx().hir().node_to_string(id) ); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5bd6b0704426b..7f2994fd79b98 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -290,7 +290,7 @@ impl<'hir> Map<'hir> { #[track_caller] pub fn parent_id(self, hir_id: HirId) -> HirId { self.opt_parent_id(hir_id) - .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id))) + .unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id))) } pub fn get_parent(self, hir_id: HirId) -> Node<'hir> { @@ -1191,12 +1191,10 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { } fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { - let id_str = format!(" (hir_id={})", id); - let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id()); let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default(); - let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str); + let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str()); match map.find(id) { Some(Node::Item(item)) => { @@ -1225,10 +1223,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::TraitAlias(..) => "trait alias", ItemKind::Impl { .. } => "impl", }; - format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str) + format!("{id} ({item_str} {})", path_str(item.owner_id.def_id)) } Some(Node::ForeignItem(item)) => { - format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str) + format!("{id} (foreign item {})", path_str(item.owner_id.def_id)) } Some(Node::ImplItem(ii)) => { let kind = match ii.kind { @@ -1236,7 +1234,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ImplItemKind::Fn(..) => "method", ImplItemKind::Type(_) => "assoc type", }; - format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str) + format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } Some(Node::TraitItem(ti)) => { let kind = match ti.kind { @@ -1245,13 +1243,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { TraitItemKind::Type(..) => "assoc type", }; - format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str) + format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) } Some(Node::Variant(ref variant)) => { - format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str) + format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id)) } Some(Node::Field(ref field)) => { - format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str) + format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } Some(Node::AnonConst(_)) => node_str("const"), Some(Node::Expr(_)) => node_str("expr"), @@ -1269,16 +1267,15 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Some(Node::Infer(_)) => node_str("infer"), Some(Node::Local(_)) => node_str("local"), Some(Node::Ctor(ctor)) => format!( - "ctor {}{}", + "{id} (ctor {})", ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)), - id_str ), Some(Node::Lifetime(_)) => node_str("lifetime"), Some(Node::GenericParam(ref param)) => { - format!("generic_param {}{}", path_str(param.def_id), id_str) + format!("{id} (generic_param {})", path_str(param.def_id)) } - Some(Node::Crate(..)) => String::from("root_crate"), - None => format!("unknown node{}", id_str), + Some(Node::Crate(..)) => String::from("(root_crate)"), + None => format!("{id} (unknown node)"), } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b63b9e754cf46..f98172e420162 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2171,7 +2171,7 @@ impl<'tcx> TyCtxt<'tcx> { self.late_bound_vars_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) .unwrap_or_else(|| { - bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) + bug!("No bound vars found for {}", self.hir().node_to_string(id)) }) .iter(), ) diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 79a6c730d7159..9beaac87183a7 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -372,7 +372,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> { self.node_type_opt(id).unwrap_or_else(|| { - bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id))) + bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id))) }) } @@ -551,9 +551,8 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) { fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) { ty::tls::with(|tcx| { bug!( - "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}", + "node {} cannot be placed in TypeckResults with hir_owner {:?}", tcx.hir().node_to_string(hir_id), - hir_id.owner, hir_owner ) }); diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index d143adb2eb941..de0e50a65de6e 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -74,37 +74,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { .expect("owning item has no entry"); if max != self.hir_ids_seen.len() - 1 { - // Collect the missing ItemLocalIds - let missing: Vec<_> = (0..=max as u32) - .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i))) - .collect(); - - // Try to map those to something more useful - let mut missing_items = Vec::with_capacity(missing.len()); + let hir = self.tcx.hir(); + let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose(); - for local_id in missing { - let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) }; + let missing_items: Vec<_> = (0..=max as u32) + .map(|i| ItemLocalId::from_u32(i)) + .filter(|&local_id| !self.hir_ids_seen.contains(local_id)) + .map(|local_id| hir.node_to_string(HirId { owner, local_id })) + .collect(); - trace!("missing hir id {:#?}", hir_id); + let seen_items: Vec<_> = self + .hir_ids_seen + .iter() + .map(|local_id| hir.node_to_string(HirId { owner, local_id })) + .collect(); - missing_items.push(format!( - "[local_id: {}, owner: {}]", - local_id, - self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose() - )); - } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}", - self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(), - max, - missing_items, - self.hir_ids_seen - .iter() - .map(|local_id| HirId { owner, local_id }) - .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h))) - .collect::>() + Max ItemLocalId = {}, missing IDs = {:#?}; seen IDs = {:#?}", + pretty_owner, max, missing_items, seen_items ) }); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b35b9d62759c7..87dbf7c3fd699 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -133,7 +133,7 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> { .cloned() .unwrap_or_else(|| { bug!( - "node_type: no type for node `{}`", + "node_type: no type for node {}", ty::tls::with(|tcx| tcx .hir() .node_to_string(await_expr.hir_id)) From e30cd18fcc8905d5c726b371cb6c1c4e081bc5f2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 2 Feb 2023 10:22:44 +1100 Subject: [PATCH 5/8] Reinstate the `hir-stats.rs` tests on stage 1. --- tests/ui/stats/hir-stats.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs index 0b89d0b160b3d..9bb87026b6418 100644 --- a/tests/ui/stats/hir-stats.rs +++ b/tests/ui/stats/hir-stats.rs @@ -1,7 +1,11 @@ // check-pass // compile-flags: -Zhir-stats // only-x86_64 -// ignore-stage1 FIXME: remove after next bootstrap bump + +// Type layouts sometimes change. When that happens, until the next bootstrap +// bump occurs, stage1 and stage2 will give different outputs for this test. +// Add an `ignore-stage1` comment marker to work around that problem during +// that time. // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. From 9dd5d3e8e421193be34fa822ab485de115174421 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 15 Jan 2023 21:31:04 +0000 Subject: [PATCH 6/8] Recover _ as .. in field pattern --- .../locales/en-US/parse.ftl | 4 ++-- compiler/rustc_parse/src/errors.rs | 5 +++- compiler/rustc_parse/src/parser/pat.rs | 18 +++++++++------ ...ssue-46718-struct-pattern-dotdotdot.stderr | 7 +++++- tests/ui/parser/issue-102806.stderr | 7 +++++- tests/ui/parser/issues/issue-63135.stderr | 7 +++++- ...uct-enum-ignoring-field-with-underscore.rs | 3 +-- ...enum-ignoring-field-with-underscore.stderr | 23 +++++-------------- 8 files changed, 42 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 21cf4bd789c7e..6752f05b044ee 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -535,8 +535,8 @@ parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` ar parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern -parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...` - .suggestion = to omit remaining fields, use one fewer `.` +parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}` + .suggestion = to omit remaining fields, use `..` parse_expected_comma_after_pattern_field = expected `,` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 145611923ff16..20da8ce5b6e76 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; @@ -1802,8 +1804,9 @@ pub(crate) struct EnumPatternInsteadOfIdentifier { #[diag(parse_dot_dot_dot_for_remaining_fields)] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] - #[suggestion(code = "..", applicability = "machine-applicable")] + #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")] pub span: Span, + pub token_str: Cow<'static, str>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 88c75fd81e758..c982d7f99a91b 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -963,12 +963,15 @@ impl<'a> Parser<'a> { } ate_comma = false; - if self.check(&token::DotDot) || self.token == token::DotDotDot { + if self.check(&token::DotDot) + || self.check_noexpect(&token::DotDotDot) + || self.check_keyword(kw::Underscore) + { etc = true; let mut etc_sp = self.token.span; - self.recover_one_fewer_dotdot(); - self.bump(); // `..` || `...` + self.recover_bad_dot_dot(); + self.bump(); // `..` || `...` || `_` if self.token == token::CloseDelim(Delimiter::Brace) { etc_span = Some(etc_sp); @@ -1061,14 +1064,15 @@ impl<'a> Parser<'a> { Ok((fields, etc)) } - /// Recover on `...` as if it were `..` to avoid further errors. + /// Recover on `...` or `_` as if it were `..` to avoid further errors. /// See issue #46718. - fn recover_one_fewer_dotdot(&self) { - if self.token != token::DotDotDot { + fn recover_bad_dot_dot(&self) { + if self.token == token::DotDot { return; } - self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span }); + let token_str = pprust::token_to_string(&self.token); + self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str }); } fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> { diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr index bfe1ed32859b9..589b2c3784926 100644 --- a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr +++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr @@ -2,7 +2,12 @@ error: expected field pattern, found `...` --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55 | LL | PersonalityInventory { expressivity: exp, ... } => exp - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | PersonalityInventory { expressivity: exp, .. } => exp + | ~~ error: aborting due to previous error diff --git a/tests/ui/parser/issue-102806.stderr b/tests/ui/parser/issue-102806.stderr index 6872b8bc0afec..ba8174a823b2a 100644 --- a/tests/ui/parser/issue-102806.stderr +++ b/tests/ui/parser/issue-102806.stderr @@ -32,7 +32,12 @@ error: expected field pattern, found `...` --> $DIR/issue-102806.rs:21:22 | LL | let V3 { z: val, ... } = v; - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | let V3 { z: val, .. } = v; + | ~~ error[E0063]: missing fields `x` and `y` in initializer of `V3` --> $DIR/issue-102806.rs:17:13 diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr index 80e9ac5bedf13..e0dc356d5467b 100644 --- a/tests/ui/parser/issues/issue-63135.stderr +++ b/tests/ui/parser/issues/issue-63135.stderr @@ -20,7 +20,12 @@ error: expected field pattern, found `...` --> $DIR/issue-63135.rs:3:8 | LL | fn i(n{...,f # - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | fn i(n{..,f # + | ~~ error: expected `}`, found `,` --> $DIR/issue-63135.rs:3:11 diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs index c30b8a1e1f1a7..b569993c6143e 100644 --- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs @@ -7,6 +7,5 @@ fn main() { let foo = Some(Foo::Other); if let Some(Foo::Bar {_}) = foo {} - //~^ ERROR expected identifier, found reserved identifier `_` - //~| ERROR pattern does not mention field `bar` [E0027] + //~^ ERROR expected field pattern, found `_` } diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr index 16f751444a558..2f3a150e5cba9 100644 --- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr @@ -1,24 +1,13 @@ -error: expected identifier, found reserved identifier `_` +error: expected field pattern, found `_` --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27 | LL | if let Some(Foo::Bar {_}) = foo {} - | ^ expected identifier, found reserved identifier - -error[E0027]: pattern does not mention field `bar` - --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17 - | -LL | if let Some(Foo::Bar {_}) = foo {} - | ^^^^^^^^^^^^ missing field `bar` - | -help: include the missing field in the pattern + | ^ | -LL | if let Some(Foo::Bar {_, bar }) = foo {} - | ~~~~~~~ -help: if you don't care about this missing field, you can explicitly ignore it +help: to omit remaining fields, use `..` | -LL | if let Some(Foo::Bar {_, .. }) = foo {} - | ~~~~~~ +LL | if let Some(Foo::Bar {..}) = foo {} + | ~~ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0027`. From 9fe8ae792e4efd59ea37116a44391b4abdd2d7be Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 1 Feb 2023 10:42:20 +0000 Subject: [PATCH 7/8] Rename `rust_2015` => `is_rust_2015` --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_resolve/src/build_reduced_graph.rs | 6 +++--- compiler/rustc_resolve/src/diagnostics.rs | 8 +++++--- compiler/rustc_resolve/src/ident.rs | 5 +++-- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_session/src/session.rs | 4 ++-- compiler/rustc_span/src/edition.rs | 2 +- compiler/rustc_span/src/lib.rs | 4 ++-- 11 files changed, 21 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index fa8567eac6090..d7767efa9841b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -131,7 +131,7 @@ pub fn print_crate<'a>( // Currently, in Rust 2018 we don't have `extern crate std;` at the crate // root, so this is not needed, and actually breaks things. - if edition.rust_2015() { + if edition.is_rust_2015() { // `#![no_std]` let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP); s.print_attribute(&fake_attr); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 81fd084ccb38e..628e9d88cf1df 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2247,7 +2247,7 @@ impl<'a> Parser<'a> { let ext = self.parse_extern(case); if let Async::Yes { span, .. } = asyncness { - if span.rust_2015() { + if span.is_rust_2015() { self.sess.emit_err(AsyncFnIn2015 { span, help: HelpUseLatestEdition::new() }); } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306cbcff149f7..ba16be29f4ee2 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -673,7 +673,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (!self.token.uninterpolated_span().rust_2015() + && (!self.token.uninterpolated_span().is_rust_2015() || self.look_ahead(1, |t| { (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star)) && !can_continue_type_after_non_fn_ident(t) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 84421dc1f6225..2fb62ce53ba6e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -265,7 +265,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let ident = path.segments.get(0).expect("empty path in visibility").ident; let crate_root = if ident.is_path_segment_keyword() { None - } else if ident.span.rust_2015() { + } else if ident.span.is_rust_2015() { Some(Segment::from_ident(Ident::new( kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()), @@ -435,10 +435,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // appears, so imports in braced groups can have roots prepended independently. let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob); let crate_root = match prefix_iter.peek() { - Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => { Some(seg.ident.span.ctxt()) } - None if is_glob && use_tree.span.rust_2015() => Some(use_tree.span.ctxt()), + None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()), _ => None, } .map(|ctxt| { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3bf041cebcb88..a08ae0f184bb2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -462,7 +462,9 @@ impl<'a> Resolver<'a> { let first_name = match path.get(0) { // In the 2018 edition this lint is a hard error, so nothing to do - Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name, + Some(seg) if seg.ident.span.is_rust_2015() && self.session.is_rust_2015() => { + seg.ident.name + } _ => return, }; @@ -1717,7 +1719,7 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )), ) - } else if self.session.rust_2015() { + } else if self.session.is_rust_2015() { ( format!("maybe a missing crate `{ident}`?"), Some(( @@ -1996,7 +1998,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { mut path: Vec, parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Option)> { - if path[1].ident.span.rust_2015() { + if path[1].ident.span.is_rust_2015() { return None; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1c985d43658ae..d03ccf256fad7 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -85,7 +85,7 @@ impl<'a> Resolver<'a> { // 4c. Standard library prelude (de-facto closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled). - let rust_2015 = ctxt.edition().rust_2015(); + let rust_2015 = ctxt.edition().is_rust_2015(); let (ns, macro_kind, is_absolute_path) = match scope_set { ScopeSet::All(ns, _) => (ns, None, false), ScopeSet::AbsolutePath(ns) => (ns, None, true), @@ -1397,7 +1397,8 @@ impl<'a> Resolver<'a> { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } - if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() { + if name == kw::PathRoot && ident.span.is_rust_2015() && self.session.rust_2018() + { // `::a::b` from 2015 macro on 2018 global edition module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); continue; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 83932c089b311..3ca10ac50baa6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2145,7 +2145,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let segments = &use_tree.prefix.segments; if !segments.is_empty() { let ident = segments[0].ident; - if ident.is_path_segment_keyword() || ident.span.rust_2015() { + if ident.is_path_segment_keyword() || ident.span.is_rust_2015() { return; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 37beff37c1fb9..cee0a7f3c203d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1343,7 +1343,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { "!", Applicability::MaybeIncorrect, ); - if path_str == "try" && span.rust_2015() { + if path_str == "try" && span.is_rust_2015() { err.note("if you want the `try` keyword, you need Rust 2018 or later"); } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 746e0f169bcf3..dbd419c1406f8 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -919,8 +919,8 @@ impl Session { } /// Is this edition 2015? - pub fn rust_2015(&self) -> bool { - self.edition().rust_2015() + pub fn is_rust_2015(&self) -> bool { + self.edition().is_rust_2015() } /// Are we allowed to use features from the Rust 2018 edition? diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index e66ec07904341..f16db69aae232 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -77,7 +77,7 @@ impl Edition { } /// Is this edition 2015? - pub fn rust_2015(self) -> bool { + pub fn is_rust_2015(self) -> bool { self == Edition::Edition2015 } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 006102a5f2fcf..e095cf3fda20d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -705,8 +705,8 @@ impl Span { } #[inline] - pub fn rust_2015(self) -> bool { - self.edition().rust_2015() + pub fn is_rust_2015(self) -> bool { + self.edition().is_rust_2015() } #[inline] From a7f97a7689197e5d87fd26390cfdb387185a7376 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 1 Feb 2023 10:44:59 +0000 Subject: [PATCH 8/8] Use `rust_2018` instead of `!is_rust_2015` --- compiler/rustc_parse/src/parser/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index ba16be29f4ee2..18aa20cee421f 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -673,7 +673,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (!self.token.uninterpolated_span().is_rust_2015() + && (self.token.uninterpolated_span().rust_2018() || self.look_ahead(1, |t| { (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star)) && !can_continue_type_after_non_fn_ident(t)