diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 5d09018759191..57ffed19c0085 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -952,6 +952,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn likely(b: bool) -> bool; /// Hints to the compiler that branch condition is likely to be false. @@ -960,6 +961,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn unlikely(b: bool) -> bool; /// Executes a breakpoint trap, for inspection by a debugger. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index aeb52bffbf24c..f55ae9a05c18c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] #![feature(const_type_name)] +#![feature(const_likely)] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs index b164b21913d6e..d7bddcd305e83 100644 --- a/src/librustc_feature/accepted.rs +++ b/src/librustc_feature/accepted.rs @@ -262,9 +262,9 @@ declare_features! ( /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254), None), /// Allows the use of `if` and `match` in constants. - (accepted, const_if_match, "1.45.0", Some(49146), None), + (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows the use of `loop` and `while` in constants. - (accepted, const_loop, "1.45.0", Some(52000), None), + (accepted, const_loop, "1.46.0", Some(52000), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 77b3d26463dfe..2f4b1bbd3ba0f 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -51,8 +51,9 @@ pub enum TokenKind { // Multi-char tokens: /// "// comment" LineComment, - /// "/* block comment */" - /// Block comments can be recursive, so the sequence like "/* /* */" + /// `/* block comment */` + /// + /// Block comments can be recursive, so the sequence like `/* /* */` /// will not be considered terminated and will result in a parsing error. BlockComment { terminated: bool }, /// Any whitespace characters sequence. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 88ba28dab82e1..01eb2d0b8e266 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -409,6 +409,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); self.copy_op(self.operand_index(args[0], index)?, dest)?; } + sym::likely | sym::unlikely => { + // These just return their argument + self.copy_op(args[0], dest)?; + } // FIXME(#73156): Handle source code coverage in const eval sym::count_code_region => (), _ => return Ok(false), diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index ca1f0aecd048a..f00fc96e5915a 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if is_lang_panic_fn(self.tcx, def_id) { self.check_op(ops::Panic); } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) { - // Exempt unstable const fns inside of macros with + // Exempt unstable const fns inside of macros or functions with // `#[allow_internal_unstable]`. - if !self.span.allows_unstable(feature) { + use crate::transform::qualify_min_const_fn::lib_feature_allowed; + if !self.span.allows_unstable(feature) + && !lib_feature_allowed(self.tcx, self.def_id, feature) + { self.check_op(ops::FnCallUnstable(def_id, feature)); } } else { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 5a3663384fb87..2f5257080cd5c 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo .map_or(false, |mut features| features.any(|name| name == feature_gate)) } +/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`. +pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { + // All features require that the corresponding gate be enabled, + // even if the function has `#[allow_internal_unstable(the_gate)]`. + if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) { + return false; + } + + // If this crate is not using stability attributes, or this function is not claiming to be a + // stable `const fn`, that is all that is required. + if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { + return true; + } + + // However, we cannot allow stable `const fn`s to use unstable features without an explicit + // opt-in via `allow_internal_unstable`. + attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) + .map_or(false, |mut features| features.any(|name| name == feature_gate)) +} + fn check_terminator( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, @@ -367,8 +387,17 @@ fn check_terminator( fn_span: _, } => { let fn_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = fn_ty.kind { - if !crate::const_eval::is_min_const_fn(tcx, def_id) { + if let ty::FnDef(fn_def_id, _) = fn_ty.kind { + // Allow unstable const if we opt in by using #[allow_internal_unstable] + // on function or macro declaration. + if !crate::const_eval::is_min_const_fn(tcx, fn_def_id) + && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id) + .map(|feature| { + span.allows_unstable(feature) + || lib_feature_allowed(tcx, def_id, feature) + }) + .unwrap_or(false) + { return Err(( span, format!( @@ -380,10 +409,10 @@ fn check_terminator( )); } - check_operand(tcx, func, span, def_id, body)?; + check_operand(tcx, func, span, fn_def_id, body)?; for arg in args { - check_operand(tcx, arg, span, def_id, body)?; + check_operand(tcx, arg, span, fn_def_id, body)?; } Ok(()) } else { diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index fc9ffc3092447..16a118cb48c91 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -376,7 +376,14 @@ impl<'a> Parser<'a> { /// let _ = vec![1, 2, 3].into_iter().collect::>>>(); /// ^^ help: remove extra angle brackets /// ``` - pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { + /// + /// If `true` is returned, then trailing brackets were recovered, tokens were consumed + /// up until one of the tokens in 'end' was encountered, and an error was emitted. + pub(super) fn check_trailing_angle_brackets( + &mut self, + segment: &PathSegment, + end: &[&TokenKind], + ) -> bool { // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -409,7 +416,7 @@ impl<'a> Parser<'a> { parsed_angle_bracket_args, ); if !parsed_angle_bracket_args { - return; + return false; } // Keep the span at the start so we can highlight the sequence of `>` characters to be @@ -447,18 +454,18 @@ impl<'a> Parser<'a> { number_of_gt, number_of_shr, ); if number_of_gt < 1 && number_of_shr < 1 { - return; + return false; } // Finally, double check that we have our end token as otherwise this is the // second case. if self.look_ahead(position, |t| { trace!("check_trailing_angle_brackets: t={:?}", t); - *t == end + end.contains(&&t.kind) }) { // Eat from where we started until the end token so that parsing can continue // as if we didn't have those extra angle brackets. - self.eat_to_tokens(&[&end]); + self.eat_to_tokens(end); let span = lo.until(self.token.span); let total_num_of_gt = number_of_gt + number_of_shr * 2; @@ -473,7 +480,9 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); + return true; } + false } /// Check to see if a pair of chained operators looks like an attempt at chained comparison, @@ -1415,7 +1424,7 @@ impl<'a> Parser<'a> { if self.token != token::Lt { err.span_suggestion( pat.span, - "if this was a parameter name, give it a type", + "if this is a parameter name, give it a type", format!("{}: TypeName", ident), Applicability::HasPlaceholders, ); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 2745b18a8cd51..fb38fdc26c782 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -867,7 +867,7 @@ impl<'a> Parser<'a> { let fn_span_lo = self.token.span; let segment = self.parse_path_segment(PathStyle::Expr)?; - self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); + self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); if self.check(&token::OpenDelim(token::Paren)) { // Method call `expr.f()` diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 10df16964da08..fa6264c98e4f0 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind}; +use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::ptr::P; use rustc_ast::token::{self, TokenKind}; @@ -1262,6 +1262,25 @@ impl<'a> Parser<'a> { sp, &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), ); + + // Try to recover extra trailing angle brackets + let mut recovered = false; + if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind { + if let Some(last_segment) = segments.last() { + recovered = self.check_trailing_angle_brackets( + last_segment, + &[&token::Comma, &token::CloseDelim(token::Brace)], + ); + if recovered { + // Handle a case like `Vec>,` where we can continue parsing fields + // after the comma + self.eat(&token::Comma); + // `check_trailing_angle_brackets` already emitted a nicer error + err.cancel(); + } + } + } + if self.token.is_ident() { // This is likely another field; emit the diagnostic and keep going err.span_suggestion( @@ -1271,6 +1290,14 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); err.emit(); + recovered = true; + } + + if recovered { + // Make sure an error was emitted (either by recovering an angle bracket, + // or by finding an identifier as the next token), since we're + // going to continue parsing + assert!(self.sess.span_diagnostic.has_errors()); } else { return Err(err); } diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5210614548da3..67e9b3af4a8cf 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -169,7 +169,7 @@ impl<'a> Parser<'a> { // `PathStyle::Expr` is only provided at the root invocation and never in // `parse_path_segment` to recurse and therefore can be checked to maintain // this invariant. - self.check_trailing_angle_brackets(&segment, token::ModSep); + self.check_trailing_angle_brackets(&segment, &[&token::ModSep]); } segments.push(segment); diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 6dcb1430cdc17..046554067f4ce 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -309,7 +309,9 @@ impl Ord for Span { } } -/// A collection of spans. Spans have two orthogonal attributes: +/// A collection of `Span`s. +/// +/// Spans have two orthogonal attributes: /// /// - They can be *primary spans*. In this case they are the locus of /// the error, and would be rendered with `^^^`. diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 857734037afe7..e2f0d0b94c46c 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -427,6 +427,7 @@ symbols! { lhs, lib, lifetime, + likely, line, link, linkage, @@ -813,6 +814,7 @@ symbols! { underscore_lifetimes, uniform_paths, universal_impl_trait, + unlikely, unmarked_api, unreachable_code, unrestricted_attribute_tokens, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 640c9f3636d4b..193ab5b47ef13 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,6 +61,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, + c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput, c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr index e7a806a846820..840294db0830a 100644 --- a/src/test/ui/anon-params/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: i32); | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(i32: TypeName); | ^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar_with_default_impl(self: String, String) {} | ^^^^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String: TypeName, String) {} | ^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | fn bar_with_default_impl(String, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | fn baz(a:usize, b, c: usize) -> usize { | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn baz(a:usize, b: TypeName, c: usize) -> usize { | ^^^^^^^^^^^ diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index 6f19ee9c7dc0d..5c4272504e061 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -20,7 +20,7 @@ fn pattern((i32, i32) (a, b)) {} fn fizz(i32) {} //~^ ERROR expected one of `:`, `@` -//~| HELP if this was a parameter name, give it a type +//~| HELP if this is a parameter name, give it a type //~| HELP if this is a `self` type, give it a parameter name //~| HELP if this is a type, explicitly ignore the parameter name diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index 043ff65f74e1a..ae180af93e373 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -39,7 +39,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn fizz(self: i32) {} | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn fizz(i32: TypeName) {} | ^^^^^^^^^^^^^ diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index 9f138bf84ce19..bc3329dcbc23d 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: x) { | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(x: TypeName) { | ^^^^^^^^^^^ diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.rs b/src/test/ui/parser/recover-field-extra-angle-brackets.rs new file mode 100644 index 0000000000000..5e0e00bcb5e8d --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.rs @@ -0,0 +1,14 @@ +// Tests that we recover from extra trailing angle brackets +// in a struct field + +struct BadStruct { + first: Vec>, //~ ERROR unmatched angle bracket + second: bool +} + +fn bar(val: BadStruct) { + val.first; + val.second; +} + +fn main() {} diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.stderr b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr new file mode 100644 index 0000000000000..318e55f6e99ac --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr @@ -0,0 +1,8 @@ +error: unmatched angle bracket + --> $DIR/recover-field-extra-angle-brackets.rs:5:19 + | +LL | first: Vec>, + | ^ help: remove extra angle bracket + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index 1e51567a9b1c4..5516d4a4c1c1c 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } | ^^^^^^^^^^^^^ diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 116f5ddd5b4b2..40c3219bf27b0 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -21,7 +21,7 @@ LL | fn foo(Option, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(Option, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar(self: x, y: usize) {} | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar(x: TypeName, y: usize) {} | ^^^^^^^^^^^ diff --git a/triagebot.toml b/triagebot.toml index 73ca7abfed363..51a29553fdb3d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -92,7 +92,7 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." [notify-zulip."I-nominated"] required_labels = ["T-compiler"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts -topic = "I-prioritize #{number} {title}" +topic = "I-nominated #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting.