diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 61f816f0baf8f..fb9016ca4d86e 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -50,11 +50,6 @@ attr_parsing_expects_feature_list = attr_parsing_expects_features = `{$name}` expects feature names -attr_parsing_ill_formed_attribute_input = {$num_suggestions -> - [1] attribute must be of the form {$suggestions} - *[other] valid forms for the attribute are {$suggestions} - } - attr_parsing_import_name_type_raw = import name type can only be used with link kind `raw-dylib` @@ -213,10 +208,6 @@ attr_parsing_stability_outside_std = stability attributes may not be used outsid attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) -attr_parsing_unknown_meta_item = - unknown meta item '{$item}' - .label = expected one of {$expected} - attr_parsing_unknown_version_literal = unknown version literal format, assuming it refers to a future version diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 5b4786a64ef2d..798cc10765415 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -42,7 +42,7 @@ pub fn parse_cfg( args: &ArgParser, ) -> Option { let ArgParser::List(list) = args else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; let Some(single) = list.single() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 7d3a7418f06c3..17c748fa3e687 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -25,7 +25,7 @@ impl SingleAttributeParser for OptimizeParser { fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; @@ -478,7 +478,7 @@ fn parse_tf_attribute( ) -> impl IntoIterator { let mut features = Vec::new(); let ArgParser::List(list) = args else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return features; }; if list.is_empty() { @@ -601,7 +601,7 @@ impl SingleAttributeParser for SanitizeParser { fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 97e78dfb136b9..0b7ac989346a4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -13,7 +13,7 @@ impl AttributeParser for ConfusablesParser { template!(List: &[r#""name1", "name2", ..."#]), |this, cx, args| { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/debugger.rs b/compiler/rustc_attr_parsing/src/attributes/debugger.rs index c88b795aab03d..52a66942cf939 100644 --- a/compiler/rustc_attr_parsing/src/attributes/debugger.rs +++ b/compiler/rustc_attr_parsing/src/attributes/debugger.rs @@ -21,7 +21,7 @@ impl CombineAttributeParser for DebuggerViualizerParser { args: &ArgParser, ) -> impl IntoIterator { let Some(l) = args.list() else { - cx.expected_list(args.span().unwrap_or(cx.attr_span)); + cx.expected_list(cx.attr_span, args); return None; }; let Some(single) = l.single() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index ad3e2ced60c7d..2d79e3a103d6e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -110,13 +110,12 @@ impl SingleAttributeParser for DeprecationParser { Some(get(cx, name, param.span(), param.args(), &suggestion)?); } _ => { - cx.unknown_key( + cx.expected_specific_argument( param.span(), - param.path().to_string(), if features.deprecated_suggestion() { - &["since", "note", "suggestion"] + &[sym::since, sym::note, sym::suggestion] } else { - &["since", "note"] + &[sym::since, sym::note] }, ); return None; diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index b6fea37c92aa2..16dbb04b48ebd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -106,7 +106,7 @@ impl DocParser { } Some(sym::attr) => { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index fe8f3578fe145..388553c8fd9b6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -76,7 +76,7 @@ impl CombineAttributeParser for LinkParser { return None; } _ => { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; } }; @@ -379,7 +379,7 @@ impl LinkParser { return true; } let Some(link_cfg) = item.args().list() else { - cx.expected_list(item.span()); + cx.expected_list(item.span(), item.args()); return true; }; let Some(link_cfg) = link_cfg.single() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index e4209c3edd85c..0f1ab02fca251 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -1,9 +1,7 @@ -use rustc_errors::DiagArgValue; use rustc_hir::attrs::MacroUseArgs; use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS; use super::prelude::*; -use crate::session_diagnostics::IllFormedAttributeInputLint; pub(crate) struct MacroEscapeParser; impl NoArgsAttributeParser for MacroEscapeParser { @@ -101,15 +99,8 @@ impl AttributeParser for MacroUseParser { } } } - ArgParser::NameValue(_) => { - let suggestions = cx.suggestions(); - cx.emit_err(IllFormedAttributeInputLint { - num_suggestions: suggestions.len(), - suggestions: DiagArgValue::StrListSepByAnd( - suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), - ), - span, - }); + ArgParser::NameValue(nv) => { + cx.expected_list_or_no_args(nv.args_span()); } } }, @@ -164,16 +155,8 @@ impl SingleAttributeParser for MacroExportParser { } } } - ArgParser::NameValue(_) => { - let span = cx.attr_span; - let suggestions = cx.suggestions(); - cx.emit_err(IllFormedAttributeInputLint { - num_suggestions: suggestions.len(), - suggestions: DiagArgValue::StrListSepByAnd( - suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), - ), - span, - }); + ArgParser::NameValue(nv) => { + cx.expected_list_or_no_args(nv.args_span()); return None; } }; diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index a27e1ecb707e3..673e2c902da0b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -1,7 +1,4 @@ -use rustc_errors::DiagArgValue; - use super::prelude::*; -use crate::session_diagnostics::IllFormedAttributeInputLint; pub(crate) struct MustUseParser; @@ -44,15 +41,8 @@ impl SingleAttributeParser for MustUseParser { }; Some(value_str) } - ArgParser::List(_) => { - let suggestions = cx.suggestions(); - cx.emit_err(IllFormedAttributeInputLint { - num_suggestions: suggestions.len(), - suggestions: DiagArgValue::StrListSepByAnd( - suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), - ), - span: cx.attr_span, - }); + ArgParser::List(list) => { + cx.expected_nv_or_no_args(list.span); return None; } }, diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index e1762005d4c4a..3674aa7124abb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -65,7 +65,7 @@ fn parse_derive_like( if args.no_args().is_ok() && !trait_name_mandatory { return Some((None, ThinVec::new())); } - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; let mut items = list.mixed(); @@ -96,7 +96,7 @@ fn parse_derive_like( let mut attributes = ThinVec::new(); if let Some(attrs) = items.next() { let Some(attr_list) = attrs.meta_item() else { - cx.expected_list(attrs.span()); + cx.unexpected_literal(attrs.span()); return None; }; if !attr_list.path().word_is(sym::attributes) { @@ -104,7 +104,7 @@ fn parse_derive_like( return None; } let Some(attr_list) = attr_list.args().list() else { - cx.expected_list(attrs.span()); + cx.expected_list(attrs.span(), attr_list.args()); return None; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs index cd7c84f45fe51..ac50fe33839d2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs @@ -27,7 +27,7 @@ impl SingleAttributeParser for CustomMirParser { fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; @@ -46,9 +46,8 @@ impl SingleAttributeParser for CustomMirParser { extract_value(cx, sym::dialect, arg, meta_item.span(), &mut dialect, &mut failed); } else if let Some(arg) = meta_item.word_is(sym::phase) { extract_value(cx, sym::phase, arg, meta_item.span(), &mut phase, &mut failed); - } else if let Some(word) = meta_item.path().word() { - let word = word.to_string(); - cx.unknown_key(meta_item.span(), word, &["dialect", "phase"]); + } else if let Some(..) = meta_item.path().word() { + cx.expected_specific_argument(meta_item.span(), &[sym::dialect, sym::phase]); failed = true; } else { cx.expected_name_value(meta_item.span(), None); diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 4520e4f5dbac1..9ad103f3bb8ee 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -33,7 +33,7 @@ impl CombineAttributeParser for ReprParser { let mut reprs = Vec::new(); let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return reprs; }; @@ -278,7 +278,7 @@ impl AlignParser { fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { match args { ArgParser::NoArgs | ArgParser::NameValue(_) => { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); } ArgParser::List(list) => { let Some(align) = list.single() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 571cb884c1fcd..6d4f77ef1751b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -295,7 +295,7 @@ pub(crate) fn parse_stability( let mut since = None; let ArgParser::List(list) = args else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; @@ -315,11 +315,7 @@ pub(crate) fn parse_stability( insert_value_into_option_or_error(cx, ¶m, &mut since, word.unwrap())? } _ => { - cx.emit_err(session_diagnostics::UnknownMetaItem { - span: param_span, - item: param.path().to_string(), - expected: &["feature", "since"], - }); + cx.expected_specific_argument(param_span, &[sym::feature, sym::since]); return None; } } @@ -371,7 +367,7 @@ pub(crate) fn parse_unstability( let mut old_name = None; let ArgParser::List(list) = args else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; @@ -426,11 +422,17 @@ pub(crate) fn parse_unstability( insert_value_into_option_or_error(cx, ¶m, &mut old_name, word.unwrap())? } _ => { - cx.emit_err(session_diagnostics::UnknownMetaItem { - span: param.span(), - item: param.path().to_string(), - expected: &["feature", "reason", "issue", "soft", "implied_by", "old_name"], - }); + cx.expected_specific_argument( + param.span(), + &[ + sym::feature, + sym::reason, + sym::issue, + sym::soft, + sym::implied_by, + sym::old_name, + ], + ); return None; } } diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index a9b76021a989d..ee5895a6efd0f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -22,7 +22,7 @@ impl SingleAttributeParser for SkipDuringMethodDispatchParser { let mut array = false; let mut boxed_slice = false; let Some(args) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; if args.is_empty() { diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs index 4e3478abbf4fd..431ba539b2ba2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/util.rs +++ b/compiler/rustc_attr_parsing/src/attributes/util.rs @@ -43,7 +43,7 @@ pub(crate) fn parse_single_integer( args: &ArgParser, ) -> Option { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); + cx.expected_list(cx.attr_span, args); return None; }; let Some(single) = list.single() else { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 074f3b4194aee..ec9f62bf1eb62 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -77,7 +77,7 @@ use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, RefPathParser}; use crate::session_diagnostics::{ - AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem, + AttributeParseError, AttributeParseErrorReason, ParsedDescription, }; use crate::target_checking::AllowedTargets; @@ -425,13 +425,20 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { } impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { - pub(crate) fn unknown_key( + fn emit_parse_error( &self, span: Span, - found: String, - options: &[&'static str], + reason: AttributeParseErrorReason<'_>, ) -> ErrorGuaranteed { - self.emit_err(UnknownMetaItem { span, item: found, expected: options }) + self.emit_err(AttributeParseError { + span, + attr_span: self.attr_span, + template: self.template.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, + reason, + suggestions: self.suggestions(), + }) } /// error that a string literal was expected. @@ -443,133 +450,69 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: Span, actual_literal: Option<&MetaItemLit>, ) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { + self.emit_parse_error( span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedStringLiteral { + AttributeParseErrorReason::ExpectedStringLiteral { byte_string: actual_literal.and_then(|i| { i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span)) }), }, - suggestions: self.suggestions(), - }) + ) } pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedIntegerLiteral, - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral) } - pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedList, - suggestions: self.suggestions(), - }) + pub(crate) fn expected_list(&self, span: Span, args: &ArgParser) -> ErrorGuaranteed { + let span = match args { + ArgParser::NoArgs => span, + ArgParser::List(list) => list.span, + ArgParser::NameValue(nv) => nv.args_span(), + }; + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList) } - pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span: args_span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedNoArgs, - suggestions: self.suggestions(), - }) + pub(crate) fn expected_list_or_no_args(&self, span: Span) -> ErrorGuaranteed { + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs) + } + + pub(crate) fn expected_nv_or_no_args(&self, span: Span) -> ErrorGuaranteed { + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs) + } + + pub(crate) fn expected_no_args(&self, span: Span) -> ErrorGuaranteed { + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs) } /// emit an error that a `name` was expected here pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedIdentifier, - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier) } /// emit an error that a `name = value` pair was expected at this span. The symbol can be given for /// a nicer error message talking about the specific name that was found lacking a value. pub(crate) fn expected_name_value(&self, span: Span, name: Option) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedNameValue(name), - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name)) } /// emit an error that a `name = value` pair was found where that name was already seen. pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::DuplicateKey(key), - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key)) } /// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser) /// was expected *not* to be a literal, but instead a meta item. pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::UnexpectedLiteral, - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::UnexpectedLiteral) } pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedSingleArgument, - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedSingleArgument) } pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { - span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument, - suggestions: self.suggestions(), - }) + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument) } /// produces an error along the lines of `expected one of [foo, meow]` @@ -578,19 +521,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: Span, possibilities: &[Symbol], ) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { + self.emit_parse_error( span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedSpecificArgument { + AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, list: false, }, - suggestions: self.suggestions(), - }) + ) } /// produces an error along the lines of `expected one of [foo, meow] as an argument`. @@ -600,19 +538,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: Span, possibilities: &[Symbol], ) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { + self.emit_parse_error( span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedSpecificArgument { + AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, list: true, }, - suggestions: self.suggestions(), - }) + ) } /// produces an error along the lines of `expected one of ["foo", "meow"]` @@ -621,19 +554,14 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: Span, possibilities: &[Symbol], ) -> ErrorGuaranteed { - self.emit_err(AttributeParseError { + self.emit_parse_error( span, - attr_span: self.attr_span, - template: self.template.clone(), - path: self.attr_path.clone(), - description: self.parsed_description, - reason: AttributeParseErrorReason::ExpectedSpecificArgument { + AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: true, list: false, }, - suggestions: self.suggestions(), - }) + ) } pub(crate) fn warn_empty_attribute(&mut self, span: Span) { diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 09ecfaedb5ed2..9551744d5ec53 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -177,7 +177,7 @@ impl ArgParser { match self { Self::NoArgs => Ok(()), Self::List(args) => Err(args.span), - Self::NameValue(args) => Err(args.eq_span.to(args.value_span)), + Self::NameValue(args) => Err(args.args_span()), } } } @@ -314,6 +314,10 @@ impl NameValueParser { pub fn value_as_str(&self) -> Option { self.value_as_lit().kind.str() } + + pub fn args_span(&self) -> Span { + self.eq_span.to(self.value_span) + } } fn expr_to_lit( diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index b50a7f92fcdc5..4aea4064b1c4b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -64,26 +64,6 @@ pub(crate) struct DocAttributeNotAttribute { pub attribute: Symbol, } -/// Error code: E0541 -pub(crate) struct UnknownMetaItem<'a> { - pub span: Span, - pub item: String, - pub expected: &'a [&'a str], -} - -// Manual implementation to be able to format `expected` items correctly. -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnknownMetaItem<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); - Diag::new(dcx, level, fluent::attr_parsing_unknown_meta_item) - .with_span(self.span) - .with_code(E0541) - .with_arg("item", self.item) - .with_arg("expected", expected.join(", ")) - .with_span_label(self.span, fluent::attr_parsing_label) - } -} - #[derive(Diagnostic)] #[diag(attr_parsing_missing_since, code = E0542)] pub(crate) struct MissingSince { @@ -400,15 +380,6 @@ pub(crate) struct UnusedMultiple { pub name: Symbol, } -#[derive(Diagnostic)] -#[diag(attr_parsing_ill_formed_attribute_input)] -pub(crate) struct IllFormedAttributeInputLint { - #[primary_span] - pub span: Span, - pub num_suggestions: usize, - pub suggestions: DiagArgValue, -} - #[derive(Diagnostic)] #[diag(attr_parsing_null_on_export, code = E0648)] pub(crate) struct NullOnExport { @@ -539,6 +510,8 @@ pub(crate) enum AttributeParseErrorReason<'a> { ExpectedAtLeastOneArgument, ExpectedSingleArgument, ExpectedList, + ExpectedListOrNoArgs, + ExpectedNameValueOrNoArgs, UnexpectedLiteral, ExpectedNameValue(Option), DuplicateKey(Symbol), @@ -611,6 +584,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { AttributeParseErrorReason::ExpectedList => { diag.span_label(self.span, "expected this to be a list"); } + AttributeParseErrorReason::ExpectedListOrNoArgs => { + diag.span_label(self.span, "expected a list or no arguments here"); + } + AttributeParseErrorReason::ExpectedNameValueOrNoArgs => { + diag.span_label(self.span, "didn't expect a list here"); + } AttributeParseErrorReason::DuplicateKey(key) => { diag.span_label(self.span, format!("found `{key}` used as a key more than once")); diag.code(E0538); diff --git a/compiler/rustc_error_codes/src/error_codes/E0541.md b/compiler/rustc_error_codes/src/error_codes/E0541.md index 96334088feeef..f1f97b39fa282 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0541.md +++ b/compiler/rustc_error_codes/src/error_codes/E0541.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An unknown meta item was used. Erroneous code example: -```compile_fail,E0541 +```compile_fail (no longer emitted) #[deprecated( since="1.0.0", // error: unknown meta item diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 27b66d07f98e4..12c4dd203203e 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -7,9 +7,7 @@ use std::cell::{Ref, RefCell}; use std::ops::Deref; -use std::slice::from_ref; -use hir::Expr; use hir::def::DefKind; use hir::pat_util::EnumerateAndAdjustIterator as _; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; @@ -313,7 +311,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let param_place = self.cat_rvalue(param.hir_id, param_ty); - self.walk_irrefutable_pat(¶m_place, param.pat)?; + self.fake_read_scrutinee(¶m_place, false)?; + self.walk_pat(¶m_place, param.pat, false)?; } self.consume_expr(body.value)?; @@ -455,13 +454,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx hir::ExprKind::Match(discr, arms, _) => { let discr_place = self.cat_expr(discr)?; - self.maybe_read_scrutinee( - discr, - discr_place.clone(), - arms.iter().map(|arm| arm.pat), - )?; + self.fake_read_scrutinee(&discr_place, true)?; + self.walk_expr(discr)?; - // treatment of the discriminant is handled while walking the arms. for arm in arms { self.walk_arm(&discr_place, arm)?; } @@ -598,116 +593,25 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } - fn maybe_read_scrutinee<'t>( + #[instrument(skip(self), level = "debug")] + fn fake_read_scrutinee( &self, - discr: &Expr<'_>, - discr_place: PlaceWithHirId<'tcx>, - pats: impl Iterator>, + discr_place: &PlaceWithHirId<'tcx>, + refutable: bool, ) -> Result<(), Cx::Error> { - // Matching should not always be considered a use of the place, hence - // discr does not necessarily need to be borrowed. - // We only want to borrow discr if the pattern contain something other - // than wildcards. - let mut needs_to_be_read = false; - for pat in pats { - self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { - match &pat.kind { - PatKind::Missing => unreachable!(), - PatKind::Binding(.., opt_sub_pat) => { - // If the opt_sub_pat is None, then the binding does not count as - // a wildcard for the purpose of borrowing discr. - if opt_sub_pat.is_none() { - needs_to_be_read = true; - } - } - PatKind::Never => { - // A never pattern reads the value. - // FIXME(never_patterns): does this do what I expect? - needs_to_be_read = true; - } - PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - // A `Path` pattern is just a name like `Foo`. This is either a - // named constant or else it refers to an ADT variant - - let res = self.cx.typeck_results().qpath_res(qpath, *hir_id); - match res { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { - // Named constants have to be equated with the value - // being matched, so that's a read of the value being matched. - // - // FIXME: We don't actually reads for ZSTs. - needs_to_be_read = true; - } - _ => { - // Otherwise, this is a struct/enum variant, and so it's - // only a read if we need to read the discriminant. - needs_to_be_read |= - self.is_multivariant_adt(place.place.ty(), *span); - } - } - } - PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { - // For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching - // against a multivariant enum or struct. In that case, we have to read - // the discriminant. Otherwise this kind of pattern doesn't actually - // read anything (we'll get invoked for the `...`, which may indeed - // perform some reads). - - let place_ty = place.place.ty(); - needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span); - } - PatKind::Expr(_) | PatKind::Range(..) => { - // If the PatKind is a Lit or a Range then we want - // to borrow discr. - needs_to_be_read = true; - } - PatKind::Slice(lhs, wild, rhs) => { - // We don't need to test the length if the pattern is `[..]` - if matches!((lhs, wild, rhs), (&[], Some(_), &[])) - // Arrays have a statically known size, so - // there is no need to read their length - || place.place.ty().peel_refs().is_array() - { - } else { - needs_to_be_read = true; - } - } - PatKind::Or(_) - | PatKind::Box(_) - | PatKind::Deref(_) - | PatKind::Ref(..) - | PatKind::Guard(..) - | PatKind::Wild - | PatKind::Err(_) => { - // If the PatKind is Or, Box, or Ref, the decision is made later - // as these patterns contains subpatterns - // If the PatKind is Wild or Err, the decision is made based on the other patterns - // being examined - } - } - - Ok(()) - })? - } + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), + _ => None, + }; - if needs_to_be_read { - self.borrow_expr(discr, BorrowKind::Immutable)?; + let cause = if refutable { + FakeReadCause::ForMatchedPlace(closure_def_id) } else { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; + FakeReadCause::ForLet(closure_def_id) + }; - self.delegate.borrow_mut().fake_read( - &discr_place, - FakeReadCause::ForMatchedPlace(closure_def_id), - discr_place.hir_id, - ); + self.delegate.borrow_mut().fake_read(discr_place, cause, discr_place.hir_id); - // We always want to walk the discriminant. We want to make sure, for instance, - // that the discriminant has been initialized. - self.walk_expr(discr)?; - } Ok(()) } @@ -724,12 +628,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.walk_expr(expr)?; let expr_place = self.cat_expr(expr)?; f()?; + self.fake_read_scrutinee(&expr_place, els.is_some())?; + self.walk_pat(&expr_place, pat, false)?; if let Some(els) = els { - // borrowing because we need to test the discriminant - self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter())?; self.walk_block(els)?; } - self.walk_irrefutable_pat(&expr_place, pat)?; Ok(()) } @@ -901,16 +804,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>, ) -> Result<(), Cx::Error> { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; - - self.delegate.borrow_mut().fake_read( - discr_place, - FakeReadCause::ForMatchedPlace(closure_def_id), - discr_place.hir_id, - ); self.walk_pat(discr_place, arm.pat, arm.guard.is_some())?; if let Some(ref e) = arm.guard { @@ -921,28 +814,20 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } - /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or - /// let binding, and *not* a match arm or nested pat.) - fn walk_irrefutable_pat( - &self, - discr_place: &PlaceWithHirId<'tcx>, - pat: &hir::Pat<'_>, - ) -> Result<(), Cx::Error> { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; - - self.delegate.borrow_mut().fake_read( - discr_place, - FakeReadCause::ForLet(closure_def_id), - discr_place.hir_id, - ); - self.walk_pat(discr_place, pat, false)?; - Ok(()) - } - /// The core driver for walking a pattern + /// + /// This should mirror how pattern-matching gets lowered to MIR, as + /// otherwise lowering will ICE when trying to resolve the upvars. + /// + /// However, it is okay to approximate it here by doing *more* accesses than + /// the actual MIR builder will, which is useful when some checks are too + /// cumbersome to perform here. For example, if after typeck it becomes + /// clear that only one variant of an enum is inhabited, and therefore a + /// read of the discriminant is not necessary, `walk_pat` will have + /// over-approximated the necessary upvar capture granularity. + /// + /// Do note that discrepancies like these do still create obscure corners + /// in the semantics of the language, and should be avoided if possible. #[instrument(skip(self), level = "debug")] fn walk_pat( &self, @@ -952,6 +837,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx ) -> Result<(), Cx::Error> { let tcx = self.cx.tcx(); self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { + debug!("walk_pat: pat.kind={:?}", pat.kind); + let read_discriminant = || { + self.delegate.borrow_mut().borrow(place, discr_place.hir_id, BorrowKind::Immutable); + }; + match pat.kind { PatKind::Binding(_, canonical_id, ..) => { debug!("walk_pat: binding place={:?} pat={:?}", place, pat); @@ -974,11 +864,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // binding when lowering pattern guards to ensure that the guard does not // modify the scrutinee. if has_guard { - self.delegate.borrow_mut().borrow( - place, - discr_place.hir_id, - BorrowKind::Immutable, - ); + read_discriminant(); } // It is also a borrow or copy/move of the value being matched. @@ -1014,13 +900,73 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx PatKind::Never => { // A `!` pattern always counts as an immutable read of the discriminant, // even in an irrefutable pattern. - self.delegate.borrow_mut().borrow( - place, - discr_place.hir_id, - BorrowKind::Immutable, - ); + read_discriminant(); + } + PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { + // A `Path` pattern is just a name like `Foo`. This is either a + // named constant or else it refers to an ADT variant + + let res = self.cx.typeck_results().qpath_res(qpath, *hir_id); + match res { + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { + // Named constants have to be equated with the value + // being matched, so that's a read of the value being matched. + // + // FIXME: Does the MIR code skip this read when matching on a ZST? + // If so, we can also skip it here. + read_discriminant(); + } + _ => { + // Otherwise, this is a struct/enum variant, and so it's + // only a read if we need to read the discriminant. + if self.is_multivariant_adt(place.place.ty(), *span) { + read_discriminant(); + } + } + } + } + PatKind::Expr(_) | PatKind::Range(..) => { + // When matching against a literal or range, we need to + // borrow the place to compare it against the pattern. + // + // Note that we do this read even if the range matches all + // possible values, such as 0..=u8::MAX. This is because + // we don't want to depend on consteval here. + // + // FIXME: What if the type being matched only has one + // possible value? + read_discriminant(); + } + PatKind::Struct(..) | PatKind::TupleStruct(..) => { + if self.is_multivariant_adt(place.place.ty(), pat.span) { + read_discriminant(); + } + } + PatKind::Slice(lhs, wild, rhs) => { + // We don't need to test the length if the pattern is `[..]` + if matches!((lhs, wild, rhs), (&[], Some(_), &[])) + // Arrays have a statically known size, so + // there is no need to read their length + || place.place.ty().peel_refs().is_array() + { + // No read necessary + } else { + read_discriminant(); + } + } + PatKind::Or(_) + | PatKind::Box(_) + | PatKind::Ref(..) + | PatKind::Guard(..) + | PatKind::Tuple(..) + | PatKind::Wild + | PatKind::Missing + | PatKind::Err(_) => { + // If the PatKind is Or, Box, Ref, Guard, or Tuple, the relevant accesses + // are made later as these patterns contains subpatterns. + // If the PatKind is Missing, Wild or Err, any relevant accesses are made when processing + // the other patterns that are part of the match } - _ => {} } Ok(()) @@ -1904,6 +1850,20 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } + /// Checks whether a type has multiple variants, and therefore, whether a + /// read of the discriminant might be necessary. Note that the actual MIR + /// builder code does a more specific check, filtering out variants that + /// happen to be uninhabited. + /// + /// Here, it is not practical to perform such a check, because inhabitedness + /// queries require typeck results, and typeck requires closure capture analysis. + /// + /// Moreover, the language is moving towards uninhabited variants still semantically + /// causing a discriminant read, so we *shouldn't* perform any such check. + /// + /// FIXME(never_patterns): update this comment once the aforementioned MIR builder + /// code is changed to be insensitive to inhhabitedness. + #[instrument(skip(self, span), level = "debug")] fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 445386412058b..1a2b76485f359 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -761,6 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ], /// } /// ``` + #[instrument(level = "debug", skip(self))] fn compute_min_captures( &self, closure_def_id: LocalDefId, @@ -2029,6 +2030,7 @@ struct InferBorrowKind<'tcx> { } impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { + #[instrument(skip(self), level = "debug")] fn fake_read( &mut self, place_with_id: &PlaceWithHirId<'tcx>, @@ -2119,6 +2121,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { } /// Rust doesn't permit moving fields out of a type that implements drop +#[instrument(skip(fcx), ret, level = "debug")] fn restrict_precision_for_drop_types<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, mut place: Place<'tcx>, @@ -2179,6 +2182,7 @@ fn restrict_precision_for_unsafe( /// - No unsafe block is required to capture `place`. /// /// Returns the truncated place and updated capture mode. +#[instrument(ret, level = "debug")] fn restrict_capture_precision( place: Place<'_>, curr_mode: ty::UpvarCapture, @@ -2208,6 +2212,7 @@ fn restrict_capture_precision( } /// Truncate deref of any reference. +#[instrument(ret, level = "debug")] fn adjust_for_move_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2222,6 +2227,7 @@ fn adjust_for_move_closure( } /// Truncate deref of any reference. +#[instrument(ret, level = "debug")] fn adjust_for_use_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2237,6 +2243,7 @@ fn adjust_for_use_closure( /// Adjust closure capture just that if taking ownership of data, only move data /// from enclosing stack frame. +#[instrument(ret, level = "debug")] fn adjust_for_non_move_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2559,6 +2566,7 @@ fn determine_place_ancestry_relation<'tcx>( /// // it is constrained to `'a` /// } /// ``` +#[instrument(ret, level = "debug")] fn truncate_capture_for_optimization( mut place: Place<'_>, mut curr_mode: ty::UpvarCapture, diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index a0d54354a9c63..67c12bfa7790d 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -339,6 +339,12 @@ impl<'tcx> MatchPairTree<'tcx> { if let Some(test_case) = test_case { // This pattern is refutable, so push a new match-pair node. + // + // Note: unless test_case is TestCase::Or, place must not be None. + // This means that the closure capture analysis in + // rustc_hir_typeck::upvar, and in particular the pattern handling + // code of ExprUseVisitor, must capture all of the places we'll use. + // Make sure to keep these two parts in sync! match_pairs.push(MatchPairTree { place, test_case, diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index bd6fd5a3de428..53b1f9292b3d4 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -15,6 +15,10 @@ struct Timespec { } impl Timespec { + const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1); + + const MIN: Timespec = Self::new(i64::MIN, 0); + const fn zero() -> Timespec { Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } } } @@ -209,6 +213,10 @@ pub struct SystemTime(Timespec); pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); impl SystemTime { + pub const MAX: SystemTime = SystemTime { t: Timespec::MAX }; + + pub const MIN: SystemTime = SystemTime { t: Timespec::MIN }; + pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime { SystemTime(Timespec::new(tv_sec, tv_nsec)) } diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/pal/sgx/time.rs index db4cf2804bf13..a9a448226619e 100644 --- a/library/std/src/sys/pal/sgx/time.rs +++ b/library/std/src/sys/pal/sgx/time.rs @@ -28,6 +28,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { SystemTime(usercalls::insecure_time()) } diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs index c39d715c6a6f6..d5cf70f94c987 100644 --- a/library/std/src/sys/pal/solid/time.rs +++ b/library/std/src/sys/pal/solid/time.rs @@ -10,6 +10,10 @@ pub struct SystemTime(abi::time_t); pub const UNIX_EPOCH: SystemTime = SystemTime(0); impl SystemTime { + pub const MAX: SystemTime = SystemTime(abi::time_t::MAX); + + pub const MIN: SystemTime = SystemTime(abi::time_t::MIN); + pub fn now() -> SystemTime { let rtc = unsafe { let mut out = MaybeUninit::zeroed(); diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index 28dacbe3068a7..30df6d93d0eed 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -70,6 +70,23 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = MAX_UEFI_TIME; + + pub const MIN: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1900, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: -1440, + daylight: 0, + pad1: 0, + pad2: 0, + }) + .unwrap(); + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Option { match system_time_internal::from_uefi(&t) { Some(x) => Some(Self(x)), diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index 24f13853b96b3..1b3fbeee4d900 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -30,6 +30,10 @@ pub(crate) struct Timespec { } impl SystemTime { + pub const MAX: SystemTime = SystemTime { t: Timespec::MAX }; + + pub const MIN: SystemTime = SystemTime { t: Timespec::MIN }; + #[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))] pub fn new(tv_sec: i64, tv_nsec: i64) -> Result { Ok(SystemTime { t: Timespec::new(tv_sec, tv_nsec)? }) @@ -62,6 +66,13 @@ impl fmt::Debug for SystemTime { } impl Timespec { + const MAX: Timespec = unsafe { Self::new_unchecked(i64::MAX, 1_000_000_000 - 1) }; + + // As described below, on Apple OS, dates before epoch are represented differently. + // This is not an issue here however, because we are using tv_sec = i64::MIN, + // which will cause the compatibility wrapper to not be executed at all. + const MIN: Timespec = unsafe { Self::new_unchecked(i64::MIN, 0) }; + const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec { Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } } } diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/pal/unsupported/time.rs index 6d67b538a96bf..9bdd57268fd5b 100644 --- a/library/std/src/sys/pal/unsupported/time.rs +++ b/library/std/src/sys/pal/unsupported/time.rs @@ -27,6 +27,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { panic!("time not implemented on this platform") } diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index 0d31b80e56afc..6cccf090a3fcf 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -64,6 +64,16 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime { + t: c::FILETIME { + dwLowDateTime: (i64::MAX & 0xFFFFFFFF) as u32, + dwHighDateTime: (i64::MAX >> 32) as u32, + }, + }; + + pub const MIN: SystemTime = + SystemTime { t: c::FILETIME { dwLowDateTime: 0, dwHighDateTime: 0 } }; + pub fn now() -> SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); @@ -101,8 +111,13 @@ impl SystemTime { } pub fn checked_sub_duration(&self, other: &Duration) -> Option { - let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?; - Some(SystemTime::from_intervals(intervals)) + // Windows does not support times before 1601, hence why we don't + // support negatives. In order to tackle this, we try to convert the + // resulting value into an u64, which should obviously fail in the case + // that the value is below zero. + let intervals: u64 = + self.intervals().checked_sub(checked_dur2intervals(other)?)?.try_into().ok()?; + Some(SystemTime::from_intervals(intervals as i64)) } } diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs index ae8be81c0b7c5..1e7e48183e982 100644 --- a/library/std/src/sys/pal/xous/time.rs +++ b/library/std/src/sys/pal/xous/time.rs @@ -35,6 +35,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { let result = blocking_scalar(systime_server(), GetUtcTimeMs.into()) .expect("failed to request utc time in ms"); diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 87aaf9091f1bc..67c144be14f6d 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -511,6 +511,83 @@ impl SystemTime { #[stable(feature = "assoc_unix_epoch", since = "1.28.0")] pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH; + /// Represents the maximum value representable by [`SystemTime`] on this platform. + /// + /// This value differs a lot between platforms, but it is always the case + /// that any positive addition of a [`Duration`], whose value is greater + /// than or equal to the time precision of the operating system, to + /// [`SystemTime::MAX`] will fail. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(time_systemtime_limits)] + /// use std::time::{Duration, SystemTime}; + /// + /// // Adding zero will change nothing. + /// assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX)); + /// + /// // But adding just one second will already fail ... + /// // + /// // Keep in mind that this in fact may succeed, if the Duration is + /// // smaller than the time precision of the operating system, which + /// // happens to be 1ns on most operating systems, with Windows being the + /// // notable exception by using 100ns, hence why this example uses 1s. + /// assert_eq!(SystemTime::MAX.checked_add(Duration::new(1, 0)), None); + /// + /// // Utilize this for saturating arithmetic to improve error handling. + /// // In this case, we will use a certificate with a timestamp in the + /// // future as a practical example. + /// let configured_offset = Duration::from_secs(60 * 60 * 24); + /// let valid_after = + /// SystemTime::now() + /// .checked_add(configured_offset) + /// .unwrap_or(SystemTime::MAX); + /// ``` + #[unstable(feature = "time_systemtime_limits", issue = "149067")] + pub const MAX: SystemTime = SystemTime(time::SystemTime::MAX); + + /// Represents the minimum value representable by [`SystemTime`] on this platform. + /// + /// This value differs a lot between platforms, but it is always the case + /// that any positive subtraction of a [`Duration`] from, whose value is + /// greater than or equal to the time precision of the operating system, to + /// [`SystemTime::MIN`] will fail. + /// + /// Depending on the platform, this may be either less than or equal to + /// [`SystemTime::UNIX_EPOCH`], depending on whether the operating system + /// supports the representation of timestamps before the Unix epoch or not. + /// However, it is always guaranteed that a [`SystemTime::UNIX_EPOCH`] fits + /// between a [`SystemTime::MIN`] and [`SystemTime::MAX`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(time_systemtime_limits)] + /// use std::time::{Duration, SystemTime}; + /// + /// // Subtracting zero will change nothing. + /// assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN)); + /// + /// // But subtracting just one second will already fail. + /// // + /// // Keep in mind that this in fact may succeed, if the Duration is + /// // smaller than the time precision of the operating system, which + /// // happens to be 1ns on most operating systems, with Windows being the + /// // notable exception by using 100ns, hence why this example uses 1s. + /// assert_eq!(SystemTime::MIN.checked_sub(Duration::new(1, 0)), None); + /// + /// // Utilize this for saturating arithmetic to improve error handling. + /// // In this case, we will use a cache expiry as a practical example. + /// let configured_expiry = Duration::from_secs(60 * 3); + /// let expiry_threshold = + /// SystemTime::now() + /// .checked_sub(configured_expiry) + /// .unwrap_or(SystemTime::MIN); + /// ``` + #[unstable(feature = "time_systemtime_limits", issue = "149067")] + pub const MIN: SystemTime = SystemTime(time::SystemTime::MIN); + /// Returns the system time corresponding to "now". /// /// # Examples @@ -588,6 +665,9 @@ impl SystemTime { /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. + /// + /// In the case that the `duration` is smaller than the time precision of the operating + /// system, `Some(self)` will be returned. #[stable(feature = "time_checked_add", since = "1.34.0")] pub fn checked_add(&self, duration: Duration) -> Option { self.0.checked_add_duration(&duration).map(SystemTime) @@ -596,6 +676,9 @@ impl SystemTime { /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. + /// + /// In the case that the `duration` is smaller than the time precision of the operating + /// system, `Some(self)` will be returned. #[stable(feature = "time_checked_add", since = "1.34.0")] pub fn checked_sub(&self, duration: Duration) -> Option { self.0.checked_sub_duration(&duration).map(SystemTime) diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs index be1948af91564..0ef89bb09c637 100644 --- a/library/std/tests/time.rs +++ b/library/std/tests/time.rs @@ -1,4 +1,5 @@ #![feature(duration_constants)] +#![feature(time_systemtime_limits)] use std::fmt::Debug; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -237,9 +238,34 @@ fn system_time_duration_since_max_range_on_unix() { let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0)); let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999)); + assert_eq!(min, SystemTime::MIN); + assert_eq!(max, SystemTime::MAX); + let delta_a = max.duration_since(min).expect("duration_since overflow"); let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration(); assert_eq!(Duration::MAX, delta_a); assert_eq!(Duration::MAX, delta_b); } + +#[test] +fn system_time_max_min() { + #[cfg(not(target_os = "windows"))] + /// Most (all?) non-Windows systems have nanosecond precision. + const MIN_INTERVAL: Duration = Duration::new(0, 1); + #[cfg(target_os = "windows")] + /// Windows' time precision is at 100ns. + const MIN_INTERVAL: Duration = Duration::new(0, 100); + + // First, test everything with checked_* and Duration::ZERO. + assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX)); + assert_eq!(SystemTime::MAX.checked_sub(Duration::ZERO), Some(SystemTime::MAX)); + assert_eq!(SystemTime::MIN.checked_add(Duration::ZERO), Some(SystemTime::MIN)); + assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN)); + + // Now do the same again with checked_* but try by ± the lowest time precision. + assert!(SystemTime::MAX.checked_add(MIN_INTERVAL).is_none()); + assert!(SystemTime::MAX.checked_sub(MIN_INTERVAL).is_some()); + assert!(SystemTime::MIN.checked_add(MIN_INTERVAL).is_some()); + assert!(SystemTime::MIN.checked_sub(MIN_INTERVAL).is_none()); +} diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 1566f1cb1dac6..74d99e0f1270e 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -189,8 +189,10 @@ impl OutputFormatter for JunitFormatter { compilation_time: f64, ) -> io::Result<()> { self.write_message(&format!( - "\n", - )) + "", + ))?; + self.out.write_all(b"\n")?; + Ok(()) } } diff --git a/src/doc/book b/src/doc/book index 8c0eacd5c4acb..39aeceaa3aeab 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 8c0eacd5c4acbb650497454f3a58c9e8083202a4 +Subproject commit 39aeceaa3aeab845bc4517e7a44e48727d3b9dbe diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 9cf5443d63267..c3c0f0b3da266 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 9cf5443d632673c4d41edad5e8ed8be86eeb3b8f +Subproject commit c3c0f0b3da26610138b7ba7663f60cd2c68cf184 diff --git a/src/doc/nomicon b/src/doc/nomicon index 0fe83ab28985b..9fe8fa599ad22 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0fe83ab28985b99aba36a1f0dbde3e08286fefda +Subproject commit 9fe8fa599ad228dda74f240cc32b54bc5c1aa3e6 diff --git a/src/doc/reference b/src/doc/reference index b14b4e40f53ca..50c5de90487b6 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit b14b4e40f53ca468beaf2f5d0dfb4f4c4ba6bc7b +Subproject commit 50c5de90487b68d429a30cc9466dc8f5b410128f diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 111cfae2f9c3a..7d21279e40e8f 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 111cfae2f9c3a43f7b0ff8fa68c51cc8f930637c +Subproject commit 7d21279e40e8f0e91c2a22c5148dd2d745aef8b6 diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index 34c57a63c97bb..9a7c28525f0ec 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -1,13 +1,9 @@ [book] -multilingual = false -src = "src" title = "The rustc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/rustc" edit-url-template = "https://github.com/rust-lang/rust/edit/HEAD/src/doc/rustc/{path}" -additional-css = ["theme/pagetoc.css"] -additional-js = ["theme/pagetoc.js"] [output.html.search] use-boolean-and = true diff --git a/src/doc/rustc/src/platform-support/armv7a-vex-v5.md b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md index 3677f8931dd68..68fbec2ff4b4c 100644 --- a/src/doc/rustc/src/platform-support/armv7a-vex-v5.md +++ b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md @@ -21,7 +21,7 @@ This target is cross-compiled. Dynamic linking is unsupported. `#![no_std]` crates can be built using `build-std` to build `core` and `panic_abort` and optionally `alloc`. Unwinding panics are not yet supported on this target. -`std` has only partial support due platform limitations. Notably: +`std` has only partial support due to platform limitations. Notably: - `std::process` and `std::net` are unimplemented. `std::thread` only supports sleeping and yielding, as this is a single-threaded environment. - `std::time` has full support for `Instant`, but no support for `SystemTime`. - `std::io` has full support for `stdin`/`stdout`/`stderr`. `stdout` and `stderr` both write to to USB channel 1 on this platform and are not differentiated. diff --git a/src/doc/rustc/theme/pagetoc.css b/src/doc/rustc/theme/pagetoc.css deleted file mode 100644 index fa709194f3755..0000000000000 --- a/src/doc/rustc/theme/pagetoc.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */ - -:root { - --toc-width: 270px; - --center-content-toc-shift: calc(-1 * var(--toc-width) / 2); -} - -.nav-chapters { - /* adjust width of buttons that bring to the previous or the next page */ - min-width: 50px; -} - -@media only screen { - @media (max-width: 1179px) { - .sidebar-hidden #sidetoc { - display: none; - } - } - - @media (max-width: 1439px) { - .sidebar-visible #sidetoc { - display: none; - } - } - - @media (1180px <= width <= 1439px) { - .sidebar-hidden main { - position: relative; - left: var(--center-content-toc-shift); - } - } - - @media (1440px <= width <= 1700px) { - .sidebar-visible main { - position: relative; - left: var(--center-content-toc-shift); - } - } - - #sidetoc { - margin-left: calc(100% + 20px); - } - #pagetoc { - position: fixed; - /* adjust TOC width */ - width: var(--toc-width); - height: calc(100vh - var(--menu-bar-height) - 0.67em * 4); - overflow: auto; - } - #pagetoc a { - border-left: 1px solid var(--sidebar-bg); - color: var(--fg); - display: block; - padding-bottom: 5px; - padding-top: 5px; - padding-left: 10px; - text-align: left; - text-decoration: none; - } - #pagetoc a:hover, - #pagetoc a.active { - background: var(--sidebar-bg); - color: var(--sidebar-active) !important; - } - #pagetoc .active { - background: var(--sidebar-bg); - color: var(--sidebar-active); - } - #pagetoc .pagetoc-H2 { - padding-left: 20px; - } - #pagetoc .pagetoc-H3 { - padding-left: 40px; - } - #pagetoc .pagetoc-H4 { - padding-left: 60px; - } -} - -@media print { - #sidetoc { - display: none; - } -} diff --git a/src/doc/rustc/theme/pagetoc.js b/src/doc/rustc/theme/pagetoc.js deleted file mode 100644 index 927a5b10749b5..0000000000000 --- a/src/doc/rustc/theme/pagetoc.js +++ /dev/null @@ -1,104 +0,0 @@ -// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) - -let activeHref = location.href; -function updatePageToc(elem = undefined) { - let selectedPageTocElem = elem; - const pagetoc = document.getElementById("pagetoc"); - - function getRect(element) { - return element.getBoundingClientRect(); - } - - function overflowTop(container, element) { - return getRect(container).top - getRect(element).top; - } - - function overflowBottom(container, element) { - return getRect(container).bottom - getRect(element).bottom; - } - - // We've not selected a heading to highlight, and the URL needs updating - // so we need to find a heading based on the URL - if (selectedPageTocElem === undefined && location.href !== activeHref) { - activeHref = location.href; - for (const pageTocElement of pagetoc.children) { - if (pageTocElement.href === activeHref) { - selectedPageTocElem = pageTocElement; - } - } - } - - // We still don't have a selected heading, let's try and find the most - // suitable heading based on the scroll position - if (selectedPageTocElem === undefined) { - const margin = window.innerHeight / 3; - - const headers = document.getElementsByClassName("header"); - for (let i = 0; i < headers.length; i++) { - const header = headers[i]; - if (selectedPageTocElem === undefined && getRect(header).top >= 0) { - if (getRect(header).top < margin) { - selectedPageTocElem = header; - } else { - selectedPageTocElem = headers[Math.max(0, i - 1)]; - } - } - // a very long last section's heading is over the screen - if (selectedPageTocElem === undefined && i === headers.length - 1) { - selectedPageTocElem = header; - } - } - } - - // Remove the active flag from all pagetoc elements - for (const pageTocElement of pagetoc.children) { - pageTocElement.classList.remove("active"); - } - - // If we have a selected heading, set it to active and scroll to it - if (selectedPageTocElem !== undefined) { - for (const pageTocElement of pagetoc.children) { - if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) { - pageTocElement.classList.add("active"); - if (overflowTop(pagetoc, pageTocElement) > 0) { - pagetoc.scrollTop = pageTocElement.offsetTop; - } - if (overflowBottom(pagetoc, pageTocElement) < 0) { - pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement); - } - } - } - } -} - -if (document.getElementById("sidetoc") === null && - document.getElementsByClassName("header").length > 0) { - // The sidetoc element doesn't exist yet, let's create it - - // Create the empty sidetoc and pagetoc elements - const sidetoc = document.createElement("div"); - const pagetoc = document.createElement("div"); - sidetoc.id = "sidetoc"; - pagetoc.id = "pagetoc"; - sidetoc.appendChild(pagetoc); - - // And append them to the current DOM - const main = document.querySelector('main'); - main.insertBefore(sidetoc, main.firstChild); - - // Populate sidebar on load - window.addEventListener("load", () => { - for (const header of document.getElementsByClassName("header")) { - const link = document.createElement("a"); - link.innerHTML = header.innerHTML; - link.href = header.hash; - link.classList.add("pagetoc-" + header.parentElement.tagName); - document.getElementById("pagetoc").appendChild(link); - link.onclick = () => updatePageToc(link); - } - updatePageToc(); - }); - - // Update page table of contents selected heading on scroll - window.addEventListener("scroll", () => updatePageToc()); -} diff --git a/src/doc/rustdoc/src/read-documentation/in-doc-settings.md b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md index 12928a4f36926..1bcf74e39cd15 100644 --- a/src/doc/rustdoc/src/read-documentation/in-doc-settings.md +++ b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md @@ -4,7 +4,7 @@ Rustdoc's HTML output includes a settings menu, and this chapter describes what each setting in this menu does. It can be accessed by clicking on the gear button -() in the upper right. +() in the upper right. ## Changing displayed theme diff --git a/src/doc/style-guide/book.toml b/src/doc/style-guide/book.toml index 056aec8cdd4f6..1ef0af5fcdbf7 100644 --- a/src/doc/style-guide/book.toml +++ b/src/doc/style-guide/book.toml @@ -1,8 +1,6 @@ [book] title = "The Rust Style Guide" -author = "The Rust Style Team" -multilingual = false -src = "src" +authors = ["The Rust Style Team"] [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/" diff --git a/src/doc/unstable-book/book.toml b/src/doc/unstable-book/book.toml index 5dbe90cd10ec6..c357949f6c2e9 100644 --- a/src/doc/unstable-book/book.toml +++ b/src/doc/unstable-book/book.toml @@ -1,6 +1,5 @@ [book] title = "The Rust Unstable Book" -author = "The Rust Community" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/unstable-book" diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 48842c8739c02..248a147cfd77c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -889,7 +889,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "pre 1.29.0"] pub SEARCH_IS_SOME, - complexity, + nursery, "using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)" } diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.rs b/src/tools/clippy/tests/ui/crashes/ice-9041.rs index 4b2a0f9531148..fae3233ba2f51 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9041.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-9041.rs @@ -1,3 +1,4 @@ +#![warn(clippy::search_is_some)] pub struct Thing; //@no-rustfix pub fn has_thing(things: &[Thing]) -> bool { diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr index dd9db71c5de83..256c8b8330344 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/crashes/ice-9041.rs:5:19 + --> tests/ui/crashes/ice-9041.rs:6:19 | LL | things.iter().find(|p| is_thing_ready(p)).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))` diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed index 1213fdcf61197..daae41c0c891b 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed @@ -311,19 +311,23 @@ mod issue9120 { } } +// skip this test due to rust-lang/rust-clippy#16086 +/* #[allow(clippy::match_like_matches_macro)] fn issue15102() { let values = [None, Some(3)]; - let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0)); - //~^ search_is_some + let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); + ~^ search_is_some println!("{has_even}"); let has_even = values .iter() - .any(|v| match &v { - //~^ search_is_some + .find(|v| match v { + ~^ search_is_some Some(x) if x % 2 == 0 => true, _ => false, - }); + }) + .is_some(); println!("{has_even}"); } +*/ diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs index 4294a39333f20..ead101a491a6a 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs @@ -322,20 +322,23 @@ mod issue9120 { } } +// skip this test due to rust-lang/rust-clippy#16086 +/* #[allow(clippy::match_like_matches_macro)] fn issue15102() { let values = [None, Some(3)]; let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); - //~^ search_is_some + ~^ search_is_some println!("{has_even}"); let has_even = values .iter() .find(|v| match v { - //~^ search_is_some + ~^ search_is_some Some(x) if x % 2 == 0 => true, _ => false, }) .is_some(); println!("{has_even}"); } +*/ diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr index cee1eb08876ba..c56fe859aac09 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr @@ -346,32 +346,5 @@ error: called `is_some()` after searching an `Iterator` with `find` LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))` -error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:328:34 - | -LL | let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))` - -error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:334:10 - | -LL | .find(|v| match v { - | __________^ -LL | | -LL | | Some(x) if x % 2 == 0 => true, -LL | | _ => false, -LL | | }) -LL | | .is_some(); - | |__________________^ - | -help: consider using - | -LL ~ .any(|v| match &v { -LL + -LL + Some(x) if x % 2 == 0 => true, -LL + _ => false, -LL ~ }); - | - -error: aborting due to 51 previous errors +error: aborting due to 49 previous errors diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index 54fe7f6eb5a9b..9d0f3b061d476 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" workspace = "../rustbook" [dependencies] -mdbook = { version = "0.4", default-features = false, features = ["search"] } +mdbook-driver = { version = "0.5.1", features = ["search"] } +mdbook-summary = "0.5.1" [[bin]] name = "error_index_generator" diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 58224aed14879..97ac47918c092 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -12,8 +12,10 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::str::FromStr; -use mdbook::book::{BookItem, Chapter, parse_summary}; -use mdbook::{Config, MDBook}; +use mdbook_driver::MDBook; +use mdbook_driver::book::{BookItem, Chapter}; +use mdbook_driver::config::Config; +use mdbook_summary::parse_summary; use rustc_errors::codes::DIAGNOSTICS; enum OutputFormat { @@ -121,7 +123,7 @@ This page lists all the error codes emitted by the Rust compiler. source_path: None, parent_names: Vec::new(), }; - book.book.sections.push(BookItem::Chapter(chapter)); + book.book.items.push(BookItem::Chapter(chapter)); book.build()?; // The error-index used to be generated manually (without mdbook), and the diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.rs b/src/tools/miri/tests/fail/closures/deref-in-pattern.rs new file mode 100644 index 0000000000000..c729469c78b0e --- /dev/null +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.rs @@ -0,0 +1,20 @@ +// This test serves to document the change in semantics introduced by +// rust-lang/rust#138961. +// +// A corollary of partial-pattern.rs: while the tuple access testcase makes +// it clear why these semantics are useful, it is actually the dereference +// being performed by the pattern that matters. + +fn main() { + // the inner reference is dangling + let x: &&u32 = unsafe { + let x: u32 = 42; + &&* &raw const x + }; + + let _ = || { //~ ERROR: encountered a dangling reference + match x { + &&_y => {}, + } + }; +} diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr new file mode 100644 index 0000000000000..1264f4e3fb95a --- /dev/null +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) + --> tests/fail/closures/deref-in-pattern.rs:LL:CC + | +LL | let _ = || { + | _____________^ +LL | | match x { +LL | | &&_y => {}, +LL | | } +LL | | }; + | |_____^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.rs b/src/tools/miri/tests/fail/closures/partial-pattern.rs new file mode 100644 index 0000000000000..cb64462081802 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/partial-pattern.rs @@ -0,0 +1,28 @@ +// This test serves to document the change in semantics introduced by +// rust-lang/rust#138961. +// +// Previously, the closure would capture the entirety of x, and access *(*x).0 +// when called. Now, the closure only captures *(*x).0, which means that +// a &*(*x).0 reborrow happens when the closure is constructed. +// +// Hence, if one of the references is dangling, this constitutes newly introduced UB +// in the case where the closure doesn't get called. This isn't a big deal, +// because while opsem only now considers this to be UB, the unsafe code +// guidelines have long recommended against any handling of dangling references. + +fn main() { + // the inner references are dangling + let x: &(&u32, &u32) = unsafe { + let a = 21; + let b = 37; + let ra = &* &raw const a; + let rb = &* &raw const b; + &(ra, rb) + }; + + let _ = || { //~ ERROR: encountered a dangling reference + match x { + (&_y, _) => {}, + } + }; +} diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/closures/partial-pattern.stderr new file mode 100644 index 0000000000000..5b7ee35ecc736 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/partial-pattern.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) + --> tests/fail/closures/partial-pattern.rs:LL:CC + | +LL | let _ = || { + | _____________^ +LL | | match x { +LL | | (&_y, _) => {}, +LL | | } +LL | | }; + | |_____^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.rs b/src/tools/miri/tests/fail/closures/uninhabited-variant.rs new file mode 100644 index 0000000000000..9c50fdc13a35f --- /dev/null +++ b/src/tools/miri/tests/fail/closures/uninhabited-variant.rs @@ -0,0 +1,31 @@ +// Motivated by rust-lang/rust#138961, this shows how invalid discriminants interact with +// closure captures. +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1, // 1 + V2(!), // 2 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 2u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + let f = || { + // After rust-lang/rust#138961, constructing the closure performs a reborrow of r. + // Nevertheless, the discriminant is only actually inspected when the closure + // is called. + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1 => {} + E::V2(_) => {} + } + }; + + f(); +} diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr new file mode 100644 index 0000000000000..995a5e3eac146 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/closures/uninhabited-variant.rs:LL:CC + | +LL | match r { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside closure at tests/fail/closures/uninhabited-variant.rs:LL:CC +note: inside `main` + --> tests/fail/closures/uninhabited-variant.rs:LL:CC + | +LL | f(); + | ^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index d5aa7a671636c..e7b04260e4a95 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -17,19 +17,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ammonia" -version = "4.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" -dependencies = [ - "cssparser", - "html5ever", - "maplit", - "tendril", - "url", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -110,6 +97,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "2.10.0" @@ -125,17 +127,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bstr" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" -dependencies = [ - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" version = "3.19.0" @@ -191,16 +182,6 @@ dependencies = [ "anstyle", "clap_lex", "strsim", - "terminal_size", -] - -[[package]] -name = "clap_complete" -version = "4.5.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971" -dependencies = [ - "clap", ] [[package]] @@ -261,29 +242,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cssparser" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf 0.11.3", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "darling" version = "0.20.11" @@ -372,17 +330,6 @@ dependencies = [ "crypto-common", ] -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "doc-comment" version = "0.3.4" @@ -390,19 +337,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] -name = "dtoa" -version = "1.0.10" +name = "ego-tree" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" [[package]] name = "elasticlunr-rs" @@ -416,29 +354,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -459,7 +374,19 @@ dependencies = [ name = "error_index_generator" version = "0.0.0" dependencies = [ - "mdbook", + "mdbook-driver", + "mdbook-summary", +] + +[[package]] +name = "fancy-regex" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998b056554fbe42e03ae0e152895cd1a7e1002aec800fdc6635d20270260c46f" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", ] [[package]] @@ -491,13 +418,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "form_urlencoded" -version = "1.2.2" +name = "font-awesome-as-a-crate" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] +checksum = "932dcfbd51320af5f27f1ba02d2e567dec332cac7d2c221ba45d8e767264c4dc" [[package]] name = "futf" @@ -558,9 +482,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -576,13 +500,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "html5ever" -version = "0.35.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" +checksum = "6452c4751a24e1b99c3260d505eaeee76a050573e61f30ac2c924ddc7236f01e" dependencies = [ "log", "markup5ever", - "match_token", ] [[package]] @@ -624,119 +547,17 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - [[package]] name = "indexmap" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown", @@ -754,30 +575,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "jiff" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "js-sys" version = "0.3.82" @@ -815,12 +612,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - [[package]] name = "lock_api" version = "0.4.14" @@ -842,17 +633,11 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "markup5ever" -version = "0.35.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" +checksum = "6c3294c4d74d0742910f8c7b466f44dda9eb2d5742c1e430138df290a1e8451c" dependencies = [ "log", "tendril", @@ -860,58 +645,91 @@ dependencies = [ ] [[package]] -name = "match_token" -version = "0.35.0" +name = "matchers" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "proc-macro2", - "quote", - "syn", + "regex-automata", ] [[package]] -name = "mdbook" -version = "0.4.52" +name = "mdbook-core" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c284d2855916af7c5919cf9ad897cfc77d3c2db6f55429c7cfb769182030ec" +checksum = "39a3873d4afac65583f1acb56ff058df989d5b4a2464bb02c785549727d307ee" dependencies = [ - "ammonia", "anyhow", - "chrono", - "clap", - "clap_complete", + "regex", + "serde", + "serde_json", + "toml 0.9.8", + "tracing", +] + +[[package]] +name = "mdbook-driver" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a229930b29a9908560883e1f386eae25d8a971d259a80f49916a50627f04a42d" +dependencies = [ + "anyhow", + "indexmap", + "mdbook-core", + "mdbook-html", + "mdbook-markdown", + "mdbook-preprocessor", + "mdbook-renderer", + "mdbook-summary", + "regex", + "serde", + "serde_json", + "shlex", + "tempfile", + "toml 0.9.8", + "topological-sort", + "tracing", +] + +[[package]] +name = "mdbook-html" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dee80c03c65e3212fb528b8c9be5568a6a85cf795d03cf9fd6ba39ad52069ca" +dependencies = [ + "anyhow", + "ego-tree", "elasticlunr-rs", - "env_logger", + "font-awesome-as-a-crate", "handlebars", "hex", - "log", - "memchr", - "opener", - "pulldown-cmark 0.10.3", + "html5ever", + "indexmap", + "mdbook-core", + "mdbook-markdown", + "mdbook-renderer", + "pulldown-cmark 0.13.0", "regex", "serde", "serde_json", "sha2", - "shlex", - "tempfile", - "toml 0.5.11", - "topological-sort", + "tracing", ] [[package]] name = "mdbook-i18n-helpers" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5644bf29b95683ea60979e30188221c374965c3a1dc0ad2d5c69e867dc0c09dc" +checksum = "82a64b6c27dc99a20968cc85a89dcfe0d36f82e2c9bc3b4342a2ffc55158822f" dependencies = [ "anyhow", "chrono", "dateparser", - "mdbook", + "mdbook-preprocessor", + "mdbook-renderer", "polib", - "pulldown-cmark 0.12.2", - "pulldown-cmark-to-cmark 20.0.1", + "pulldown-cmark 0.13.0", + "pulldown-cmark-to-cmark 21.1.0", "regex", "semver", "serde_json", @@ -919,15 +737,50 @@ dependencies = [ "textwrap", ] +[[package]] +name = "mdbook-markdown" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c41bf35212f5d8b83e543aa6a4887dc5709c8489c5fb9ed00f1b51ce1a2cc6" +dependencies = [ + "pulldown-cmark 0.13.0", + "regex", + "tracing", +] + +[[package]] +name = "mdbook-preprocessor" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d87bf40be0597f26f0822f939a64f02bf92c4655ba04490aadbf83601a013bb" +dependencies = [ + "anyhow", + "mdbook-core", + "serde", + "serde_json", +] + +[[package]] +name = "mdbook-renderer" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ed59f225b3ae4283c56bea633db83184627a090d892908bd66990c68e10b43" +dependencies = [ + "anyhow", + "mdbook-core", + "serde", + "serde_json", +] + [[package]] name = "mdbook-spec" version = "0.1.2" dependencies = [ "anyhow", - "mdbook", + "mdbook-markdown", + "mdbook-preprocessor", "once_cell", "pathdiff", - "pulldown-cmark 0.10.3", "railroad", "regex", "semver", @@ -936,6 +789,20 @@ dependencies = [ "walkdir", ] +[[package]] +name = "mdbook-summary" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d85b291d67a69c92e939450390fe34d6ea418a868c8f7b42f0b300af35a7b" +dependencies = [ + "anyhow", + "mdbook-core", + "memchr", + "pulldown-cmark 0.13.0", + "serde", + "tracing", +] + [[package]] name = "mdbook-trpl" version = "0.1.0" @@ -943,9 +810,10 @@ dependencies = [ "anyhow", "clap", "html_parser", - "mdbook", + "mdbook-preprocessor", "pulldown-cmark 0.12.2", "pulldown-cmark-to-cmark 19.0.1", + "serde", "serde_json", "thiserror 1.0.69", "toml 0.8.23", @@ -974,10 +842,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "normpath" -version = "1.5.0" +name = "nu-ansi-term" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ "windows-sys 0.61.2", ] @@ -1018,39 +886,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "onig" -version = "6.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" -dependencies = [ - "bitflags", - "libc", - "once_cell", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "opener" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9024962ab91e00c89d2a14352a8d0fc1a64346bf96f1839b45c09149564e47" -dependencies = [ - "bstr", - "normpath", - "windows-sys 0.60.2", -] - [[package]] name = "parking_lot" version = "0.12.5" @@ -1080,12 +915,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - [[package]] name = "pest" version = "2.8.3" @@ -1129,23 +958,13 @@ dependencies = [ "sha2", ] -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros", - "phf_shared 0.11.3", -] - [[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_shared 0.13.1", + "phf_shared", "serde", ] @@ -1155,18 +974,8 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand", + "phf_generator", + "phf_shared", ] [[package]] @@ -1176,29 +985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", + "phf_shared", ] [[package]] @@ -1211,10 +998,10 @@ dependencies = [ ] [[package]] -name = "pkg-config" -version = "0.3.32" +name = "pin-project-lite" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "polib" @@ -1225,30 +1012,6 @@ dependencies = [ "linereader", ] -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1266,35 +1029,29 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.10.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" dependencies = [ "bitflags", + "getopts", "memchr", - "pulldown-cmark-escape 0.10.1", + "pulldown-cmark-escape", "unicase", ] [[package]] name = "pulldown-cmark" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" dependencies = [ "bitflags", - "getopts", "memchr", - "pulldown-cmark-escape 0.11.0", + "pulldown-cmark-escape", "unicase", ] -[[package]] -name = "pulldown-cmark-escape" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" - [[package]] name = "pulldown-cmark-escape" version = "0.11.0" @@ -1312,11 +1069,11 @@ dependencies = [ [[package]] name = "pulldown-cmark-to-cmark" -version = "20.0.1" +version = "21.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c0f333311d2d8fda65bcf76af35054e9f38e253332a0289746156a59656988b" +checksum = "8246feae3db61428fd0bb94285c690b460e4517d83152377543ca802357785f1" dependencies = [ - "pulldown-cmark 0.12.2", + "pulldown-cmark 0.13.0", ] [[package]] @@ -1343,21 +1100,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1401,12 +1143,11 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap", - "env_logger", - "libc", - "mdbook", + "mdbook-driver", "mdbook-i18n-helpers", "mdbook-spec", "mdbook-trpl", + "tracing-subscriber", ] [[package]] @@ -1507,6 +1248,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1518,6 +1268,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1542,12 +1301,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "string_cache" version = "0.9.0" @@ -1556,7 +1309,7 @@ checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared 0.13.1", + "phf_shared", "precomputed-hash", "serde", ] @@ -1567,8 +1320,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -1590,17 +1343,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "syntect" version = "5.3.0" @@ -1608,10 +1350,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" dependencies = [ "bincode", + "fancy-regex", "flate2", "fnv", "once_cell", - "onig", "regex-syntax", "serde", "serde_derive", @@ -1643,16 +1385,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "terminal_size" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" -dependencies = [ - "rustix", - "windows-sys 0.60.2", -] - [[package]] name = "textwrap" version = "0.16.2" @@ -1700,34 +1432,39 @@ dependencies = [ ] [[package]] -name = "tinystr" -version = "0.8.2" +name = "thread_local" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "displaydoc", - "zerovec", + "cfg-if", ] [[package]] name = "toml" -version = "0.5.11" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit", ] [[package]] name = "toml" -version = "0.8.23" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "indexmap", + "serde_core", + "serde_spanned 1.0.3", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow", ] [[package]] @@ -1739,6 +1476,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -1747,24 +1493,100 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_write", "winnow", ] +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + [[package]] name = "topological-sort" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" +[[package]] +name = "tracing" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "typenum" version = "1.19.0" @@ -1795,36 +1617,24 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" @@ -1897,11 +1707,11 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b72896d90cfd22c495d0ee4960d3dd20ca64180895cb92cd5342ff7482a579" +checksum = "acd0c322f146d0f8aad130ce6c187953889359584497dac6561204c8e17bb43d" dependencies = [ - "phf 0.13.1", + "phf", "phf_codegen", "string_cache", "string_cache_codegen", @@ -2072,86 +1882,3 @@ name = "wit-bindgen" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 1a5b2c29d20be..2815f09105b1b 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -8,14 +8,9 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] -clap = "4.0.32" -env_logger = "0.11" -libc = "0.2" -mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" } -mdbook-i18n-helpers = "0.3.3" +clap = { version = "4.0.32", features = ["cargo"] } +mdbook-driver = { version = "0.5.2", features = ["search"] } +mdbook-i18n-helpers = "0.4.0" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } - -[dependencies.mdbook] -version = "0.4.52" -default-features = false -features = ["search"] +mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" } +tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 4b510e308c977..5410524028205 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -2,15 +2,27 @@ use std::env; use std::path::{Path, PathBuf}; use clap::{ArgMatches, Command, arg, crate_version}; -use mdbook::MDBook; -use mdbook::errors::Result as Result3; +use mdbook_driver::MDBook; +use mdbook_driver::errors::Result as Result3; use mdbook_i18n_helpers::preprocessors::Gettext; use mdbook_spec::Spec; use mdbook_trpl::{Figure, Listing, Note}; fn main() { let crate_version = concat!("v", crate_version!()); - env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); + let filter = tracing_subscriber::EnvFilter::builder() + .with_env_var("MDBOOK_LOG") + .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) + .from_env_lossy(); + tracing_subscriber::fmt() + .without_time() + .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr())) + .with_writer(std::io::stderr) + .with_env_filter(filter) + .with_target(std::env::var_os("MDBOOK_LOG").is_some()) + .init(); + + // env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let d_arg = arg!(-d --"dest-dir" "The output directory for your book\n(Defaults to ./book when omitted)") .required(false) @@ -82,12 +94,45 @@ fn main() { }; } -// Build command implementation -pub fn build(args: &ArgMatches) -> Result3<()> { +fn build(args: &ArgMatches) -> Result3<()> { let book_dir = get_book_dir(args); - let mut book = load_book(&book_dir)?; + let dest_dir = args.get_one::("dest-dir"); + let lang = args.get_one::("lang"); + let rust_root = args.get_one::("rust-root"); + let book = load_book(&book_dir, dest_dir, lang, rust_root.cloned())?; + book.build() +} + +fn test(args: &ArgMatches) -> Result3<()> { + let book_dir = get_book_dir(args); + let mut book = load_book(&book_dir, None, None, None)?; + let library_paths = args + .try_get_one::>("library-path")? + .map(|v| v.iter().map(|s| s.as_str()).collect::>()) + .unwrap_or_default(); + book.test(library_paths) +} + +fn get_book_dir(args: &ArgMatches) -> PathBuf { + if let Some(p) = args.get_one::("dir") { + // Check if path is relative from current dir, or absolute... + if p.is_relative() { env::current_dir().unwrap().join(p) } else { p.to_path_buf() } + } else { + env::current_dir().unwrap() + } +} + +fn load_book( + book_dir: &Path, + dest_dir: Option<&PathBuf>, + lang: Option<&String>, + rust_root: Option, +) -> Result3 { + let mut book = MDBook::load(book_dir)?; + book.config.set("output.html.input-404", "").unwrap(); + book.config.set("output.html.hash-files", true).unwrap(); - if let Some(lang) = args.get_one::("lang") { + if let Some(lang) = lang { let gettext = Gettext; book.with_preprocessor(gettext); book.config.set("book.language", lang).unwrap(); @@ -96,7 +141,7 @@ pub fn build(args: &ArgMatches) -> Result3<()> { // Set this to allow us to catch bugs in advance. book.config.build.create_missing = false; - if let Some(dest_dir) = args.get_one::("dest-dir") { + if let Some(dest_dir) = dest_dir { book.config.build.build_dir = dest_dir.into(); } @@ -107,51 +152,22 @@ pub fn build(args: &ArgMatches) -> Result3<()> { // This should probably be fixed in mdbook to remove the existing // preprocessor, or this should modify the config and use // MDBook::load_with_config. - if book.config.get_preprocessor("trpl-note").is_some() { + if book.config.contains_key("preprocessor.trpl-note") { book.with_preprocessor(Note); } - if book.config.get_preprocessor("trpl-listing").is_some() { + if book.config.contains_key("preprocessor.trpl-listing") { book.with_preprocessor(Listing); } - if book.config.get_preprocessor("trpl-figure").is_some() { + if book.config.contains_key("preprocessor.trpl-figure") { book.with_preprocessor(Figure); } - if book.config.get_preprocessor("spec").is_some() { - let rust_root = args.get_one::("rust-root").cloned(); + if book.config.contains_key("preprocessor.spec") { book.with_preprocessor(Spec::new(rust_root)?); } - book.build()?; - - Ok(()) -} - -fn test(args: &ArgMatches) -> Result3<()> { - let book_dir = get_book_dir(args); - let library_paths = args - .try_get_one::>("library-path")? - .map(|v| v.iter().map(|s| s.as_str()).collect::>()) - .unwrap_or_default(); - let mut book = load_book(&book_dir)?; - book.test(library_paths) -} - -fn get_book_dir(args: &ArgMatches) -> PathBuf { - if let Some(p) = args.get_one::("dir") { - // Check if path is relative from current dir, or absolute... - if p.is_relative() { env::current_dir().unwrap().join(p) } else { p.to_path_buf() } - } else { - env::current_dir().unwrap() - } -} - -fn load_book(book_dir: &Path) -> Result3 { - let mut book = MDBook::load(book_dir)?; - book.config.set("output.html.input-404", "").unwrap(); - book.config.set("output.html.hash-files", true).unwrap(); Ok(book) } @@ -159,7 +175,7 @@ fn parse_library_paths(input: &str) -> Result, String> { Ok(input.split(",").map(String::from).collect()) } -fn handle_error(error: mdbook::errors::Error) -> ! { +fn handle_error(error: mdbook_driver::errors::Error) -> ! { eprintln!("Error: {}", error); for cause in error.chain().skip(1) { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 592ba9c5c7946..1a9a3401ab16c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -1,6 +1,7 @@ //! Checks the licenses of third-party dependencies. use std::collections::{HashMap, HashSet}; +use std::fmt::{Display, Formatter}; use std::fs::{File, read_dir}; use std::io::Write; use std::path::Path; @@ -14,6 +15,25 @@ use crate::diagnostics::{RunningCheck, TidyCtx}; #[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"] mod proc_macro_deps; +#[derive(Clone, Copy)] +struct ListLocation { + path: &'static str, + line: u32, +} + +impl Display for ListLocation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}", self.path, self.line) + } +} + +/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start); +macro_rules! location { + (+ $offset:literal) => { + ListLocation { path: file!(), line: line!() + $offset } + }; +} + /// These are licenses that are allowed for all crates, including the runtime, /// rustc, tools, etc. #[rustfmt::skip] @@ -87,6 +107,8 @@ pub(crate) struct WorkspaceInfo<'a> { pub(crate) submodules: &'a [&'a str], } +const WORKSPACE_LOCATION: ListLocation = location!(+4); + /// The workspaces to check for licensing and optionally permitted dependencies. // FIXME auto detect all cargo workspaces pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ @@ -222,10 +244,14 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[ // tidy-alphabetical-start - ("cssparser", "MPL-2.0"), - ("cssparser-macros", "MPL-2.0"), - ("dtoa-short", "MPL-2.0"), - ("mdbook", "MPL-2.0"), + ("font-awesome-as-a-crate", "CC-BY-4.0 AND MIT"), + ("mdbook-core", "MPL-2.0"), + ("mdbook-driver", "MPL-2.0"), + ("mdbook-html", "MPL-2.0"), + ("mdbook-markdown", "MPL-2.0"), + ("mdbook-preprocessor", "MPL-2.0"), + ("mdbook-renderer", "MPL-2.0"), + ("mdbook-summary", "MPL-2.0"), // tidy-alphabetical-end ]; @@ -242,19 +268,6 @@ const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[]; const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[]; -#[derive(Clone, Copy)] -struct ListLocation { - path: &'static str, - line: u32, -} - -/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start); -macro_rules! location { - (+ $offset:literal) => { - ListLocation { path: file!(), line: line!() + $offset } - }; -} - const PERMITTED_RUSTC_DEPS_LOCATION: ListLocation = location!(+6); /// Crates rustc is allowed to depend on. Avoid adding to the list if possible. @@ -641,6 +654,13 @@ pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) { .other_options(vec!["--locked".to_owned()]); let metadata = t!(cmd.exec()); + // Check for packages which have been moved into a different workspace and not updated + let absolute_root = + if path == "." { root.to_path_buf() } else { t!(std::path::absolute(root.join(path))) }; + let absolute_root_real = t!(std::path::absolute(&metadata.workspace_root)); + if absolute_root_real != absolute_root { + check.error(format!("{path} is part of another workspace ({} != {}), remove from `WORKSPACES` ({WORKSPACE_LOCATION})", absolute_root.display(), absolute_root_real.display())); + } check_license_exceptions(&metadata, path, exceptions, &mut check); if let Some((crates, permitted_deps, location)) = crates_and_deps { let descr = crates.get(0).unwrap_or(&path); diff --git a/tests/crashes/119786.rs b/tests/crashes/119786-1.rs similarity index 100% rename from tests/crashes/119786.rs rename to tests/crashes/119786-1.rs diff --git a/tests/crashes/119786-2.rs b/tests/crashes/119786-2.rs new file mode 100644 index 0000000000000..76c5deb4605ae --- /dev/null +++ b/tests/crashes/119786-2.rs @@ -0,0 +1,15 @@ +//@ known-bug: #119786 +//@ edition:2021 + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some(_) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/crashes/119786-3.rs b/tests/crashes/119786-3.rs new file mode 100644 index 0000000000000..34bb90fd0fae3 --- /dev/null +++ b/tests/crashes/119786-3.rs @@ -0,0 +1,15 @@ +//@ known-bug: #119786 +//@ edition:2021 + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some((a, b)) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/crashes/137467-1.rs b/tests/crashes/137467-1.rs deleted file mode 100644 index b6bff2bdc4e86..0000000000000 --- a/tests/crashes/137467-1.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 -enum Camera { - Normal { base_transform: i32 }, - Volume { transform: i32 }, -} - -fn draw_ui(camera: &mut Camera) { - || { - let (Camera::Normal { - base_transform: _transform, - } - | Camera::Volume { - transform: _transform, - }) = camera; - }; -} diff --git a/tests/crashes/137467-2.rs b/tests/crashes/137467-2.rs deleted file mode 100644 index a70ea92b22dc2..0000000000000 --- a/tests/crashes/137467-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 - -enum Camera { - Normal { base_transform: i32 }, - Volume { transform: i32 }, -} - -fn draw_ui(camera: &mut Camera) { - || { - let (Camera::Normal { - base_transform: _, - } - | Camera::Volume { - transform: _, - }) = camera; - }; -} diff --git a/tests/crashes/137467-3.rs b/tests/crashes/137467-3.rs deleted file mode 100644 index cb81a9a912e7c..0000000000000 --- a/tests/crashes/137467-3.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 - -fn meow(x: (u32, u32, u32)) { - let f = || { - let ((0, a, _) | (_, _, a)) = x; - }; -} diff --git a/tests/crashes/140011.rs b/tests/crashes/140011.rs deleted file mode 100644 index b9d57a2822d21..0000000000000 --- a/tests/crashes/140011.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #140011 -//@compile-flags: -Wrust-2021-incompatible-closure-captures -enum b { - c(d), - e(f), -} -struct f; -fn g() { - let h; - || b::e(a) = h; -} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir index b43af549b232c..9ff1a90ab820b 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir @@ -4,18 +4,16 @@ fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake yields () { debug _task_context => _2; - debug f => (*(_1.0: &&Foo)); + debug f => (*(_1.0: &Foo)); let mut _0: (); let mut _3: &Foo; let mut _4: &&Foo; - let mut _5: &&&Foo; - let mut _6: isize; - let mut _7: bool; + let mut _5: isize; + let mut _6: bool; bb0: { - PlaceMention((*(_1.0: &&Foo))); - _6 = discriminant((*(*(_1.0: &&Foo)))); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + _5 = discriminant((*(_1.0: &Foo))); + switchInt(move _5) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -32,17 +30,15 @@ yields () } bb4: { - FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo))); unreachable; } bb5: { - _3 = &fake shallow (*(*(_1.0: &&Foo))); - _4 = &fake shallow (*(_1.0: &&Foo)); - _5 = &fake shallow (_1.0: &&Foo); - StorageLive(_7); - _7 = const true; - switchInt(move _7) -> [0: bb8, otherwise: bb7]; + _3 = &fake shallow (*(_1.0: &Foo)); + _4 = &fake shallow (_1.0: &Foo); + StorageLive(_6); + _6 = const true; + switchInt(move _6) -> [0: bb8, otherwise: bb7]; } bb6: { @@ -50,10 +46,9 @@ yields () } bb7: { - StorageDead(_7); + StorageDead(_6); FakeRead(ForMatchGuard, _3); FakeRead(ForMatchGuard, _4); - FakeRead(ForMatchGuard, _5); _0 = const (); goto -> bb10; } @@ -63,7 +58,7 @@ yields () } bb9: { - StorageDead(_7); + StorageDead(_6); goto -> bb6; } diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index 5623b6d64e973..4b745caf48c5a 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -4,18 +4,16 @@ fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fa yields () { debug _task_context => _2; - debug f => (_1.0: &Foo); + debug f => (*(_1.0: &Foo)); let mut _0: (); let mut _3: &Foo; let mut _4: &&Foo; - let mut _5: &&&Foo; - let mut _6: isize; - let mut _7: bool; + let mut _5: isize; + let mut _6: bool; bb0: { - PlaceMention((_1.0: &Foo)); - _6 = discriminant((*(_1.0: &Foo))); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + _5 = discriminant((*(_1.0: &Foo))); + switchInt(move _5) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -29,24 +27,22 @@ yields () bb3: { _3 = &fake shallow (*(_1.0: &Foo)); - _4 = &fake shallow (_1.0: &Foo); nop; - StorageLive(_7); - _7 = const true; - switchInt(move _7) -> [0: bb5, otherwise: bb4]; + StorageLive(_6); + _6 = const true; + switchInt(move _6) -> [0: bb5, otherwise: bb4]; } bb4: { - StorageDead(_7); + StorageDead(_6); FakeRead(ForMatchGuard, _3); FakeRead(ForMatchGuard, _4); - FakeRead(ForMatchGuard, _5); _0 = const (); goto -> bb6; } bb5: { - StorageDead(_7); + StorageDead(_6); falseEdge -> [real: bb1, imaginary: bb1]; } diff --git a/tests/run-make/doctests-junit/doctest-2021.xml b/tests/run-make/doctests-junit/doctest-2021.xml new file mode 100644 index 0000000000000..5facfb80ce622 --- /dev/null +++ b/tests/run-make/doctests-junit/doctest-2021.xml @@ -0,0 +1 @@ + diff --git a/tests/run-make/doctests-junit/doctest-2024.xml b/tests/run-make/doctests-junit/doctest-2024.xml new file mode 100644 index 0000000000000..4f94f01c3e32c --- /dev/null +++ b/tests/run-make/doctests-junit/doctest-2024.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/run-make/doctests-junit/doctest.rs b/tests/run-make/doctests-junit/doctest.rs new file mode 100644 index 0000000000000..1873d63a49c63 --- /dev/null +++ b/tests/run-make/doctests-junit/doctest.rs @@ -0,0 +1,14 @@ +/// ``` +/// assert_eq!(doctest::add(2, 2), 4); +/// ``` +/// +/// ```should_panic +/// assert_eq!(doctest::add(2, 2), 5); +/// ``` +/// +/// ```compile_fail +/// assert_eq!(doctest::add(2, 2), "banana"); +/// ``` +pub fn add(a: i32, b: i32) -> i32 { + a + b +} diff --git a/tests/run-make/doctests-junit/rmake.rs b/tests/run-make/doctests-junit/rmake.rs new file mode 100644 index 0000000000000..4cc7ac7c31d7f --- /dev/null +++ b/tests/run-make/doctests-junit/rmake.rs @@ -0,0 +1,44 @@ +// Check rustdoc's test JUnit (XML) output against snapshots. + +//@ ignore-cross-compile (running doctests) +//@ needs-unwind (test file contains `should_panic` test) + +use std::path::Path; + +use run_make_support::{cwd, diff, python_command, rustc, rustdoc}; + +fn main() { + let rlib = cwd().join("libdoctest.rlib"); + rustc().input("doctest.rs").crate_type("rlib").output(&rlib).run(); + + run_doctests(&rlib, "2021", "doctest-2021.xml"); + run_doctests(&rlib, "2024", "doctest-2024.xml"); +} + +#[track_caller] +fn run_doctests(rlib: &Path, edition: &str, expected_xml: &str) { + let rustdoc_out = rustdoc() + .input("doctest.rs") + .args(&[ + "--test", + "--test-args=-Zunstable-options", + "--test-args=--test-threads=1", + "--test-args=--format=junit", + ]) + .edition(edition) + .env("RUST_BACKTRACE", "0") + .extern_("doctest", rlib.display().to_string()) + .run(); + let rustdoc_stdout = &rustdoc_out.stdout_utf8(); + + // FIXME: merged output of compile_fail tests is broken + if edition != "2024" { + python_command().arg("validate_junit.py").stdin_buf(rustdoc_stdout).run(); + } + + diff() + .expected_file(expected_xml) + .actual_text("output", rustdoc_stdout) + .normalize(r#"\b(time|total_time|compilation_time)="[0-9.]+""#, r#"$1="$$TIME""#) + .run(); +} diff --git a/tests/run-make/doctests-junit/validate_junit.py b/tests/run-make/doctests-junit/validate_junit.py new file mode 100755 index 0000000000000..a9cb0a059563d --- /dev/null +++ b/tests/run-make/doctests-junit/validate_junit.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Trivial Python script that reads lines from stdin, and checks that each line +# is a well-formed XML document. +# +# This takes advantage of the fact that Python has a built-in XML parser, +# whereas doing the same check in Rust would require us to pull in an XML +# crate just for this relatively-minor test. +# +# If you're trying to remove Python scripts from the test suite, think twice +# before removing this one. You could do so, but it's probably not worth it. + +import sys +import xml.etree.ElementTree as ET + +# Read the entire output and try to decode it as XML. +junit = sys.stdin.read() +try: + ET.fromstring(junit) +except ET.ParseError: + print("Invalid xml: %r" % junit) + raise diff --git a/tests/run-make/libtest-junit/validate_junit.py b/tests/run-make/libtest-junit/validate_junit.py index f92473751b036..a9cb0a059563d 100755 --- a/tests/run-make/libtest-junit/validate_junit.py +++ b/tests/run-make/libtest-junit/validate_junit.py @@ -13,10 +13,10 @@ import sys import xml.etree.ElementTree as ET -# Try to decode line in order to ensure it is a valid XML document -for line in sys.stdin: - try: - ET.fromstring(line) - except ET.ParseError: - print("Invalid xml: %r" % line) - raise +# Read the entire output and try to decode it as XML. +junit = sys.stdin.read() +try: + ET.fromstring(junit) +except ET.ParseError: + print("Invalid xml: %r" % junit) + raise diff --git a/tests/rustdoc-ui/invalid-cfg.stderr b/tests/rustdoc-ui/invalid-cfg.stderr index 84f8cea543145..5396110709692 100644 --- a/tests/rustdoc-ui/invalid-cfg.stderr +++ b/tests/rustdoc-ui/invalid-cfg.stderr @@ -2,7 +2,9 @@ error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:2:1 | LL | #[doc(cfg = "x")] - | ^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^-----^^ + | | + | expected this to be a list error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:3:1 @@ -16,7 +18,9 @@ error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:7:1 | LL | #[doc(cfg = "x")] - | ^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^-----^^ + | | + | expected this to be a list error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:8:1 @@ -30,7 +34,9 @@ error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:12:1 | LL | #[doc(cfg = "x")] - | ^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^-----^^ + | | + | expected this to be a list error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:13:1 @@ -44,7 +50,9 @@ error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:18:1 | LL | #[doc(cfg = "x")] - | ^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^-----^^ + | | + | expected this to be a list error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:19:1 diff --git a/tests/ui/attributes/invalid-macro-use.rs b/tests/ui/attributes/invalid-macro-use.rs index 52e4608303f04..4d05e933647be 100644 --- a/tests/ui/attributes/invalid-macro-use.rs +++ b/tests/ui/attributes/invalid-macro-use.rs @@ -2,7 +2,9 @@ //~^ NOTE the lint level is defined here #[macro_use = 5] -//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` +//~^ ERROR malformed `macro_use` attribute input +//~| NOTE expected a list or no arguments here +//~| NOTE for more information, visit extern crate std as s1; #[macro_use(5)] diff --git a/tests/ui/attributes/invalid-macro-use.stderr b/tests/ui/attributes/invalid-macro-use.stderr index ff3ed6196d3d3..fe235ab209f33 100644 --- a/tests/ui/attributes/invalid-macro-use.stderr +++ b/tests/ui/attributes/invalid-macro-use.stderr @@ -1,23 +1,35 @@ error[E0469]: imported macro not found - --> $DIR/invalid-macro-use.rs:51:13 + --> $DIR/invalid-macro-use.rs:53:13 | LL | #[macro_use(a)] | ^ error[E0469]: imported macro not found - --> $DIR/invalid-macro-use.rs:53:13 + --> $DIR/invalid-macro-use.rs:55:13 | LL | #[macro_use(b)] | ^ -error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` +error[E0539]: malformed `macro_use` attribute input --> $DIR/invalid-macro-use.rs:4:1 | LL | #[macro_use = 5] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^---^ + | | + | expected a list or no arguments here + | + = note: for more information, visit +help: try changing it to one of the following valid forms of the attribute + | +LL - #[macro_use = 5] +LL + #[macro_use(name1, name2, ...)] + | +LL - #[macro_use = 5] +LL + #[macro_use] + | error[E0539]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:8:1 + --> $DIR/invalid-macro-use.rs:10:1 | LL | #[macro_use(5)] | ^^^^^^^^^^^^-^^ @@ -35,7 +47,7 @@ LL + #[macro_use] | error[E0565]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:14:1 + --> $DIR/invalid-macro-use.rs:16:1 | LL | #[macro_use(a = "b")] | ^^^^^^^^^^^^^^-----^^ @@ -53,7 +65,7 @@ LL + #[macro_use] | error[E0565]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:20:1 + --> $DIR/invalid-macro-use.rs:22:1 | LL | #[macro_use(a(b))] | ^^^^^^^^^^^^^---^^ @@ -71,7 +83,7 @@ LL + #[macro_use] | error[E0539]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:26:1 + --> $DIR/invalid-macro-use.rs:28:1 | LL | #[macro_use(a::b)] | ^^^^^^^^^^^^----^^ @@ -89,13 +101,13 @@ LL + #[macro_use] | error: unused attribute - --> $DIR/invalid-macro-use.rs:32:1 + --> $DIR/invalid-macro-use.rs:34:1 | LL | #[macro_use(a)] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:34:1 + --> $DIR/invalid-macro-use.rs:36:1 | LL | #[macro_use] | ^^^^^^^^^^^^ @@ -106,25 +118,25 @@ LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/invalid-macro-use.rs:40:1 + --> $DIR/invalid-macro-use.rs:42:1 | LL | #[macro_use(a)] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:38:1 + --> $DIR/invalid-macro-use.rs:40:1 | LL | #[macro_use] | ^^^^^^^^^^^^ error: unused attribute - --> $DIR/invalid-macro-use.rs:46:1 + --> $DIR/invalid-macro-use.rs:48:1 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:44:1 + --> $DIR/invalid-macro-use.rs:46:1 | LL | #[macro_use] | ^^^^^^^^^^^^ diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 26ee89dd7b3be..37ccf9faa1a3e 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -59,7 +59,7 @@ #[cold = 1] //~^ ERROR malformed #[must_use()] -//~^ ERROR valid forms for the attribute are +//~^ ERROR malformed #[no_mangle = 1] //~^ ERROR malformed #[unsafe(naked())] @@ -214,12 +214,12 @@ static mut TLS: u8 = 42; #[no_link()] //~^ ERROR malformed #[macro_use = 1] -//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` +//~^ ERROR malformed extern crate wloop; //~^ ERROR can't find crate for `wloop` [E0463] #[macro_export = 18] -//~^ ERROR valid forms for the attribute are +//~^ ERROR malformed #[allow_internal_unsafe = 1] //~^ ERROR malformed //~| ERROR allow_internal_unsafe side-steps the unsafe_code lint diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index e1ebe4ac9eab4..0cd88e2541949 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -314,11 +314,23 @@ LL | #[cold = 1] | | didn't expect any arguments here | help: must be of the form: `#[cold]` -error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` +error[E0539]: malformed `must_use` attribute input --> $DIR/malformed-attrs.rs:61:1 | LL | #[must_use()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^--^ + | | + | didn't expect a list here + | + = note: for more information, visit +help: try changing it to one of the following valid forms of the attribute + | +LL - #[must_use()] +LL + #[must_use = "reason"] + | +LL - #[must_use()] +LL + #[must_use] + | error[E0565]: malformed `no_mangle` attribute input --> $DIR/malformed-attrs.rs:63:1 @@ -614,17 +626,40 @@ LL | #[non_exhaustive = 1] | | didn't expect any arguments here | help: must be of the form: `#[non_exhaustive]` -error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` +error[E0539]: malformed `macro_use` attribute input --> $DIR/malformed-attrs.rs:216:1 | LL | #[macro_use = 1] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^---^ + | | + | expected a list or no arguments here + | + = note: for more information, visit +help: try changing it to one of the following valid forms of the attribute + | +LL - #[macro_use = 1] +LL + #[macro_use(name1, name2, ...)] + | +LL - #[macro_use = 1] +LL + #[macro_use] + | -error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]` +error[E0539]: malformed `macro_export` attribute input --> $DIR/malformed-attrs.rs:221:1 | LL | #[macro_export = 18] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^----^ + | | + | expected a list or no arguments here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[macro_export = 18] +LL + #[macro_export(local_inner_macros)] + | +LL - #[macro_export = 18] +LL + #[macro_export] + | error[E0565]: malformed `allow_internal_unsafe` attribute input --> $DIR/malformed-attrs.rs:223:1 diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index b419df8ea2d18..ad01457d063b9 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -20,9 +20,9 @@ error[E0539]: malformed `rustc_align` attribute input --> $DIR/malformed-fn-align.rs:17:1 | LL | #[rustc_align = 16] - | ^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^^^^^^----^ + | | | + | | expected this to be a list | help: must be of the form: `#[rustc_align()]` error[E0589]: invalid alignment value: not an unsuffixed integer diff --git a/tests/ui/attributes/malformed-must_use.rs b/tests/ui/attributes/malformed-must_use.rs index 4b98affa8abd3..79a1c369f8385 100644 --- a/tests/ui/attributes/malformed-must_use.rs +++ b/tests/ui/attributes/malformed-must_use.rs @@ -1,4 +1,4 @@ -#[must_use()] //~ ERROR valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` +#[must_use()] //~ ERROR malformed struct Test; fn main() {} diff --git a/tests/ui/attributes/malformed-must_use.stderr b/tests/ui/attributes/malformed-must_use.stderr index c948ba677444f..d4797baa1b0b9 100644 --- a/tests/ui/attributes/malformed-must_use.stderr +++ b/tests/ui/attributes/malformed-must_use.stderr @@ -1,8 +1,21 @@ -error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` +error[E0539]: malformed `must_use` attribute input --> $DIR/malformed-must_use.rs:1:1 | LL | #[must_use()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^--^ + | | + | didn't expect a list here + | + = note: for more information, visit +help: try changing it to one of the following valid forms of the attribute + | +LL - #[must_use()] +LL + #[must_use = "reason"] + | +LL - #[must_use()] +LL + #[must_use] + | error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/malformed-static-align.stderr b/tests/ui/attributes/malformed-static-align.stderr index e618ca8acd75b..6f5225f7278d0 100644 --- a/tests/ui/attributes/malformed-static-align.stderr +++ b/tests/ui/attributes/malformed-static-align.stderr @@ -2,9 +2,9 @@ error[E0539]: malformed `rustc_align_static` attribute input --> $DIR/malformed-static-align.rs:4:1 | LL | #[rustc_align_static = 16] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^^^^^^^^^^^^^----^ + | | | + | | expected this to be a list | help: must be of the form: `#[rustc_align_static()]` error[E0589]: invalid alignment value: not an unsuffixed integer diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr index 094987e944fdf..04907f5d638ef 100644 --- a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr +++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr @@ -11,9 +11,9 @@ error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input --> $DIR/rustc_skip_during_method_dispatch.rs:7:1 | LL | #[rustc_skip_during_method_dispatch = "array"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------^ + | | | + | | expected this to be a list | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs index d9c06a68c95b9..4c600ccdaa438 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs @@ -22,6 +22,7 @@ fn multi_variant_enum() { //~| ERROR Min Capture analysis includes: if let Info::Point(_, _, str) = point { //~^ NOTE: Capturing point[] -> Immutable + //~| NOTE: Capturing point[] -> Immutable //~| NOTE: Capturing point[(2, 0)] -> ByValue //~| NOTE: Min Capture point[] -> ByValue println!("{}", str); @@ -29,6 +30,7 @@ fn multi_variant_enum() { if let Info::Meta(_, v) = meta { //~^ NOTE: Capturing meta[] -> Immutable + //~| NOTE: Capturing meta[] -> Immutable //~| NOTE: Capturing meta[(1, 1)] -> ByValue //~| NOTE: Min Capture meta[] -> ByValue println!("{:?}", v); diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr index 89a879cec468b..b62384ffe12e0 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -9,7 +9,7 @@ LL | let c = #[rustc_capture_analysis] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:48:13 + --> $DIR/capture-enums.rs:50:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,18 +34,28 @@ note: Capturing point[] -> Immutable | LL | if let Info::Point(_, _, str) = point { | ^^^^^ +note: Capturing point[] -> Immutable + --> $DIR/capture-enums.rs:23:41 + | +LL | if let Info::Point(_, _, str) = point { + | ^^^^^ note: Capturing point[(2, 0)] -> ByValue --> $DIR/capture-enums.rs:23:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing meta[] -> Immutable - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 + | +LL | if let Info::Meta(_, v) = meta { + | ^^^^ +note: Capturing meta[] -> Immutable + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ note: Capturing meta[(1, 1)] -> ByValue - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ @@ -67,13 +77,13 @@ note: Min Capture point[] -> ByValue LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Min Capture meta[] -> ByValue - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: First Pass analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:54:5 | LL | / || { LL | | @@ -85,13 +95,13 @@ LL | | }; | |_____^ | note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:57:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:54:5 | LL | / || { LL | | @@ -103,7 +113,7 @@ LL | | }; | |_____^ | note: Min Capture point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:57:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ diff --git a/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs new file mode 100644 index 0000000000000..b2c0eac9efa27 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs @@ -0,0 +1,54 @@ +// Newly accepted examples as a result of the changes introduced in #138961. +// +//@ edition:2024 +//@ check-pass +#![allow(unused_assignments)] + +// Reading the length as part of a pattern captures the pointee. +fn f() { + let mut x: &mut [u8] = &mut [1, 2, 3]; + let c = || { + match x { + [] => (), + _ => (), + } + }; + x = &mut []; + c(); +} + +// Plain old deref as part of pattern behaves similarly +fn g() { + let mut x: &mut bool = &mut false; + let mut t = true; + let c = || { + match x { + true => (), + false => (), + } + }; + x = &mut t; + c(); +} + +// Like f, but the lifetime implications are expressed in terms of +// returning a closure. +fn f2<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l { + || match *x { + &[] => (), + _ => (), + } +} + +// Related testcase that was already accepted before +fn f3<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l { + || match **x { + [] => (), + _ => (), + } +} + +fn main() { + f(); + g(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr index d82db0481a06f..3f5fe9eda423f 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr @@ -4,7 +4,7 @@ error[E0505]: cannot move out of `ts` because it is borrowed LL | let _b = || { match ts { | -- -- borrow occurs due to use in closure | | - | borrow of `ts` occurs here + | borrow of `ts.x` occurs here ... LL | let mut mut_ts = ts; | ^^ move out of `ts` occurs here diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index 40330af4088c2..16cb9d7355da5 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -64,9 +64,8 @@ fn test_6_should_capture_single_variant() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match variant { - //~^ NOTE: Capturing variant[] -> Immutable - //~| NOTE: Capturing variant[(0, 0)] -> Immutable - //~| NOTE: Min Capture variant[] -> Immutable + //~^ NOTE: Capturing variant[(0, 0)] -> Immutable + //~| NOTE: Min Capture variant[(0, 0)] -> Immutable SingleVariant::Points(a) => { println!("{:?}", a); } @@ -149,8 +148,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [_,_,_] => {}, _ => {} } @@ -161,8 +160,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [] => {}, _ => {} } @@ -173,8 +172,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [_, .. ,_] => {}, _ => {} } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index e7e5e7f7fa1bf..73c685e152765 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -65,11 +65,6 @@ LL | | match variant { LL | | }; | |_____^ | -note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:66:15 - | -LL | match variant { - | ^^^^^^^ note: Capturing variant[(0, 0)] -> Immutable --> $DIR/patterns-capture-analysis.rs:66:15 | @@ -87,14 +82,14 @@ LL | | match variant { LL | | }; | |_____^ | -note: Min Capture variant[] -> Immutable +note: Min Capture variant[(0, 0)] -> Immutable --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:83:5 + --> $DIR/patterns-capture-analysis.rs:82:5 | LL | / || { LL | | @@ -105,7 +100,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:95:5 + --> $DIR/patterns-capture-analysis.rs:94:5 | LL | / || { LL | | @@ -116,7 +111,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:108:5 + --> $DIR/patterns-capture-analysis.rs:107:5 | LL | / || { LL | | @@ -127,7 +122,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:130:5 + --> $DIR/patterns-capture-analysis.rs:129:5 | LL | / || { LL | | @@ -138,13 +133,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:133:15 + --> $DIR/patterns-capture-analysis.rs:132:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:130:5 + --> $DIR/patterns-capture-analysis.rs:129:5 | LL | / || { LL | | @@ -155,13 +150,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:133:15 + --> $DIR/patterns-capture-analysis.rs:132:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:148:5 + --> $DIR/patterns-capture-analysis.rs:147:5 | LL | / || { LL | | @@ -171,14 +166,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:151:15 +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:150:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:148:5 + --> $DIR/patterns-capture-analysis.rs:147:5 | LL | / || { LL | | @@ -188,14 +183,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:151:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:150:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:160:5 + --> $DIR/patterns-capture-analysis.rs:159:5 | LL | / || { LL | | @@ -205,14 +200,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:163:15 +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:162:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:160:5 + --> $DIR/patterns-capture-analysis.rs:159:5 | LL | / || { LL | | @@ -222,14 +217,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:163:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:162:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:172:5 + --> $DIR/patterns-capture-analysis.rs:171:5 | LL | / || { LL | | @@ -239,14 +234,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:175:15 +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:174:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:172:5 + --> $DIR/patterns-capture-analysis.rs:171:5 | LL | / || { LL | | @@ -256,14 +251,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:175:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:174:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:189:5 + --> $DIR/patterns-capture-analysis.rs:188:5 | LL | / || { LL | | diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs new file mode 100644 index 0000000000000..c7f367cc48ab9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs @@ -0,0 +1,22 @@ +// This example used to compile, but the fact that it should was never properly +// discussed. With further experience, we concluded that capture precision +// depending on whether some types are inhabited goes too far, introducing a +// bunch of headaches without much benefit. +//@ edition:2021 +enum Void {} + +pub fn main() { + let mut r = Result::::Err((0, 0)); + let mut f = || { + let Err((ref mut a, _)) = r; + *a = 1; + }; + let mut g = || { + //~^ ERROR: cannot borrow `r` as mutable more than once at a time + let Err((_, ref mut b)) = r; + *b = 2; + }; + f(); + g(); + assert!(matches!(r, Err((1, 2)))); +} diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr new file mode 100644 index 0000000000000..7f4c8942b0d91 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant-stable.rs:14:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr new file mode 100644 index 0000000000000..58a5348aa391a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant.rs:16:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr new file mode 100644 index 0000000000000..58a5348aa391a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant.rs:16:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs similarity index 55% rename from tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs rename to tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs index 74f37b514e4a4..4638387347269 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs @@ -1,8 +1,9 @@ -// Test precise capture of a multi-variant enum (when remaining variants are -// visibly uninhabited). +// This example used to compile, but the fact that it should was never properly +// discussed. With further experience, we concluded that capture precision +// depending on whether some types are inhabited goes too far, introducing a +// bunch of headaches without much benefit. //@ revisions: normal exhaustive_patterns //@ edition:2021 -//@ run-pass #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![feature(never_type)] @@ -13,6 +14,7 @@ pub fn main() { *a = 1; }; let mut g = || { + //~^ ERROR: cannot borrow `r` as mutable more than once at a time let Err((_, ref mut b)) = r; *b = 2; }; diff --git a/tests/ui/closures/at-pattern-weirdness-issue-137553.rs b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs new file mode 100644 index 0000000000000..7c934d4a14339 --- /dev/null +++ b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs @@ -0,0 +1,41 @@ +//@ edition:2024 +//@ check-pass + +// Background: +fn f1() { + let mut a = (21, 37); + // only captures a.0, example compiles fine + let mut f = || { + let (ref mut x, _) = a; + *x = 42; + }; + a.1 = 69; + f(); +} + +// This used to error out: +fn f2() { + let mut a = (21, 37); + // used to capture all of a, now captures only a.0 + let mut f = || { + match a { + (ref mut x, _) => *x = 42, + } + }; + a.1 = 69; + f(); +} + +// This was inconsistent with the following: +fn main() { + let mut a = (21, 37); + // the useless @-pattern would cause it to capture only a.0. now the + // behavior is consistent with the case that doesn't use the @-pattern + let mut f = || { + match a { + (ref mut x @ _, _) => *x = 42, + } + }; + a.1 = 69; + f(); +} diff --git a/tests/ui/closures/malformed-pattern-issue-140011.rs b/tests/ui/closures/malformed-pattern-issue-140011.rs new file mode 100644 index 0000000000000..18061613e9880 --- /dev/null +++ b/tests/ui/closures/malformed-pattern-issue-140011.rs @@ -0,0 +1,13 @@ +//@compile-flags: -Wrust-2021-incompatible-closure-captures +enum B { + C(D), //~ ERROR: cannot find type `D` in this scope + E(F), +} +struct F; +fn f(h: B) { + || { + let B::E(a) = h; //~ ERROR: refutable pattern in local binding + }; +} + +fn main() {} diff --git a/tests/ui/closures/malformed-pattern-issue-140011.stderr b/tests/ui/closures/malformed-pattern-issue-140011.stderr new file mode 100644 index 0000000000000..43beb7c586322 --- /dev/null +++ b/tests/ui/closures/malformed-pattern-issue-140011.stderr @@ -0,0 +1,36 @@ +error[E0425]: cannot find type `D` in this scope + --> $DIR/malformed-pattern-issue-140011.rs:3:7 + | +LL | C(D), + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | enum B { + | +++ + +error[E0005]: refutable pattern in local binding + --> $DIR/malformed-pattern-issue-140011.rs:9:13 + | +LL | let B::E(a) = h; + | ^^^^^^^ pattern `B::C(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html +note: `B` defined here + --> $DIR/malformed-pattern-issue-140011.rs:2:6 + | +LL | enum B { + | ^ +LL | C(D), + | - not covered + = note: the matched value is of type `B` +help: you might want to use `let...else` to handle the variant that isn't matched + | +LL | let B::E(a) = h else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0005, E0425. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/closures/or-patterns-issue-137467.rs b/tests/ui/closures/or-patterns-issue-137467.rs new file mode 100644 index 0000000000000..5a1e84e1c9a0d --- /dev/null +++ b/tests/ui/closures/or-patterns-issue-137467.rs @@ -0,0 +1,177 @@ +//@ edition:2024 +//@ check-pass + +const X: u32 = 0; + +fn match_literal(x: (u32, u32, u32)) { + let _ = || { + let ((0, a, _) | (_, _, a)) = x; + a + }; +} + +fn match_range(x: (u32, u32, u32)) { + let _ = || { + let ((0..5, a, _) | (_, _, a)) = x; + a + }; +} + +fn match_const(x: (u32, u32, u32)) { + let _ = || { + let ((X, a, _) | (_, _, a)) = x; + a + }; +} + +// related testcase reported in #138973 +fn without_bindings(x: u32) { + let _ = || { + let (0 | _) = x; + }; +} + +enum Choice { A, B } + +fn match_unit_variant(x: (Choice, u32, u32)) { + let _ = || { + let ((Choice::A, a, _) | (Choice::B, _, a)) = x; + a + }; +} + +struct Unit; + +fn match_unit_struct(mut x: (Unit, u32)) { + let r = &mut x.0; + let _ = || { + let (Unit, a) = x; + a + }; + + let _ = *r; +} + +enum Also { Unit } + +fn match_unit_enum(mut x: (Also, u32)) { + let r = &mut x.0; + let _ = || { + let (Also::Unit, a) = x; + a + }; + + let _ = *r; +} + +enum TEnum { + A(u32), + B(u32), +} + +enum SEnum { + A { a: u32 }, + B { a: u32 }, +} + +fn match_tuple_enum(x: TEnum) { + let _ = || { + let (TEnum::A(a) | TEnum::B(a)) = x; + a + }; +} + +fn match_struct_enum(x: SEnum) { + let _ = || { + let (SEnum::A { a } | SEnum::B { a }) = x; + a + }; +} + +enum TSingle { + A(u32, u32), +} + +enum SSingle { + A { a: u32, b: u32 }, +} + +struct TStruct(u32, u32); +struct SStruct { a: u32, b: u32 } + +fn match_struct(mut x: SStruct) { + let r = &mut x.a; + let _ = || { + let SStruct { b, .. } = x; + b + }; + + let _ = *r; +} + +fn match_tuple_struct(mut x: TStruct) { + let r = &mut x.0; + let _ = || { + let TStruct(_, a) = x; + a + }; + + let _ = *r; +} + +fn match_singleton(mut x: SSingle) { + let SSingle::A { a: ref mut r, .. } = x; + let _ = || { + let SSingle::A { b, .. } = x; + b + }; + + let _ = *r; +} + +fn match_tuple_singleton(mut x: TSingle) { + let TSingle::A(ref mut r, _) = x; + let _ = || { + let TSingle::A(_, a) = x; + a + }; + + let _ = *r; +} + +fn match_slice(x: (&[u32], u32, u32)) { + let _ = || { + let (([], a, _) | ([_, ..], _, a)) = x; + a + }; +} + +// Original testcase, for completeness +enum Camera { + Normal { base_transform: i32 }, + Volume { transform: i32 }, +} + +fn draw_ui(camera: &mut Camera) { + || { + let (Camera::Normal { + base_transform: _transform, + } + | Camera::Volume { + transform: _transform, + }) = camera; + }; +} + +fn draw_ui2(camera: &mut Camera) { + || { + let (Camera::Normal { + base_transform: _, + } + | Camera::Volume { + transform: _, + }) = camera; + }; +} + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index e73b20f2d5d31..1be52de708e5b 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -13,9 +13,9 @@ error[E0539]: malformed `cfg` attribute input --> $DIR/cfg-attr-syntax-validation.rs:7:1 | LL | #[cfg = 10] - | ^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^----^ + | | | + | | expected this to be a list | help: must be of the form: `#[cfg(predicate)]` | = note: for more information, visit diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs index 45ee91741e5a1..d1061dc1e170b 100644 --- a/tests/ui/deprecation/deprecation-sanity.rs +++ b/tests/ui/deprecation/deprecation-sanity.rs @@ -3,7 +3,7 @@ // Various checks that deprecation attributes are used correctly mod bogus_attribute_types_1 { - #[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason' + #[deprecated(since = "a", note = "a", reason)] //~ ERROR malformed `deprecated` attribute input [E0539] fn f1() { } #[deprecated(since = "a", note)] //~ ERROR malformed `deprecated` attribute input [E0539] diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index a96d4a0bdea88..a4dc9f23d3d2f 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -1,8 +1,10 @@ -error[E0541]: unknown meta item 'reason' - --> $DIR/deprecation-sanity.rs:6:43 +error[E0539]: malformed `deprecated` attribute input + --> $DIR/deprecation-sanity.rs:6:5 | LL | #[deprecated(since = "a", note = "a", reason)] - | ^^^^^^ expected one of `since`, `note` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^ + | | + | valid arguments are `since` or `note` error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:9:5 @@ -86,5 +88,5 @@ LL | #[deprecated = "hello"] error: aborting due to 10 previous errors -Some errors have detailed explanations: E0538, E0539, E0541, E0565. +Some errors have detailed explanations: E0538, E0539, E0565. For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs index 67959a3182977..274faa4495ef0 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs @@ -13,7 +13,7 @@ mod macro_escape { //~^ ERROR arguments to `macro_use` are not allowed here #[macro_use = "2700"] struct S; - //~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` + //~^ ERROR malformed //~| WARN cannot be used on //~| WARN previously accepted diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr index 5be17e96fb15f..1aa0e8fc2830c 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr @@ -16,11 +16,23 @@ error: arguments to `macro_use` are not allowed here LL | #![macro_use(my_macro)] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` +error[E0539]: malformed `macro_use` attribute input --> $DIR/issue-43106-gating-of-macro_use.rs:15:5 | LL | #[macro_use = "2700"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^--------^ + | | + | expected a list or no arguments here + | + = note: for more information, visit +help: try changing it to one of the following valid forms of the attribute + | +LL - #[macro_use = "2700"] struct S; +LL + #[macro_use(name1, name2, ...)] struct S; + | +LL - #[macro_use = "2700"] struct S; +LL + #[macro_use] struct S; + | warning: `#[macro_use]` attribute cannot be used on structs --> $DIR/issue-43106-gating-of-macro_use.rs:15:5 @@ -61,3 +73,4 @@ LL | #[macro_use] impl S { } error: aborting due to 4 previous errors; 4 warnings emitted +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr index 101df0371b542..4bf88e150f45e 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr @@ -10,7 +10,9 @@ error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-early.rs:3:1 | LL | #[link = "foo"] - | ^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^-------^ + | | + | expected this to be a list | = note: for more information, visit diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index a5f654ca0aeb5..b09431f923aaf 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -142,9 +142,9 @@ error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:24:1 | LL | #[link(name = "...", cfg = "literal")] - | ^^^^^^^^^^^^^^^^^^^^^---------------^^ - | | - | expected this to be a list + | ^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^ + | | + | expected this to be a list | = note: for more information, visit diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index f46afda1e4772..2bf6ff3a9e7a9 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -10,7 +10,9 @@ error[E0539]: malformed `link` attribute input --> $DIR/malformed-regressions.rs:10:1 | LL | #[link = ""] - | ^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^----^ + | | + | expected this to be a list | = note: for more information, visit diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr index e7127c8ef1d2e..24962cf270a4e 100644 --- a/tests/ui/proc-macro/attribute.stderr +++ b/tests/ui/proc-macro/attribute.stderr @@ -16,7 +16,9 @@ error[E0539]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:15:1 | LL | #[proc_macro_derive = ""] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^^^^^^^^^^^----^ + | | + | expected this to be a list | = note: for more information, visit help: try changing it to one of the following valid forms of the attribute diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr index e8168f8f9a582..a842590c9639e 100644 --- a/tests/ui/repr/repr.stderr +++ b/tests/ui/repr/repr.stderr @@ -10,7 +10,9 @@ error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:4:1 | LL | #[repr = "B"] - | ^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^-----^ + | | + | expected this to be a list | = note: for more information, visit @@ -18,7 +20,9 @@ error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:7:1 | LL | #[repr = "C"] - | ^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^-----^ + | | + | expected this to be a list | = note: for more information, visit diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index 2a3497678bdca..26ef31603d887 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -42,7 +42,9 @@ error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:18:1 | LL | #[sanitize = "off"] - | ^^^^^^^^^^^^^^^^^^^ expected this to be a list + | ^^^^^^^^^^^-------^ + | | + | expected this to be a list error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:21:1 diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-2.rs b/tests/ui/stability-attribute/stability-attribute-sanity-2.rs index 92e300d33d6ec..dabff97ad52dd 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-2.rs +++ b/tests/ui/stability-attribute/stability-attribute-sanity-2.rs @@ -7,7 +7,7 @@ #[stable(feature = "a", feature = "b", since = "1.0.0")] //~ ERROR malformed `stable` attribute input [E0538] fn f1() { } -#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR unknown meta item 'sinse' +#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR malformed `stable` attribute input [E0539] fn f2() { } #[unstable(feature = "a", issue = "no")] diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr index 5b35a51cad729..7beb9fd979ce7 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr @@ -7,11 +7,14 @@ LL | #[stable(feature = "a", feature = "b", since = "1.0.0")] | | found `feature` used as a key more than once | help: must be of the form: `#[stable(feature = "name", since = "version")]` -error[E0541]: unknown meta item 'sinse' - --> $DIR/stability-attribute-sanity-2.rs:10:25 +error[E0539]: malformed `stable` attribute input + --> $DIR/stability-attribute-sanity-2.rs:10:1 | LL | #[stable(feature = "a", sinse = "1.0.0")] - | ^^^^^^^^^^^^^^^ expected one of `feature`, `since` + | ^^^^^^^^^^^^^^^^^^^^^^^^---------------^^ + | | | + | | valid arguments are `feature` or `since` + | help: must be of the form: `#[stable(feature = "name", since = "version")]` error[E0545]: `issue` must be a non-zero numeric string or "none" --> $DIR/stability-attribute-sanity-2.rs:13:27 @@ -23,5 +26,5 @@ LL | #[unstable(feature = "a", issue = "no")] error: aborting due to 3 previous errors -Some errors have detailed explanations: E0538, E0541, E0545. +Some errors have detailed explanations: E0538, E0539, E0545. For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr index f656aeaa16c7f..9b3f540198ce4 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr @@ -11,9 +11,9 @@ error[E0539]: malformed `unstable` attribute input --> $DIR/stability-attribute-sanity-4.rs:11:5 | LL | #[unstable = "b"] - | ^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^^^-----^ + | | | + | | expected this to be a list | help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` error[E0539]: malformed `stable` attribute input @@ -29,9 +29,9 @@ error[E0539]: malformed `stable` attribute input --> $DIR/stability-attribute-sanity-4.rs:17:5 | LL | #[stable = "a"] - | ^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^-----^ + | | | + | | expected this to be a list | help: must be of the form: `#[stable(feature = "name", since = "version")]` error[E0542]: missing 'since' diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.rs b/tests/ui/stability-attribute/stability-attribute-sanity.rs index c4c86e12d267e..cee8d5fae1d2e 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity.rs +++ b/tests/ui/stability-attribute/stability-attribute-sanity.rs @@ -5,7 +5,7 @@ #![stable(feature = "rust1", since = "1.0.0")] mod bogus_attribute_types_1 { - #[stable(feature = "a", since = "4.4.4", reason)] //~ ERROR unknown meta item 'reason' [E0541] + #[stable(feature = "a", since = "4.4.4", reason)] //~ ERROR malformed `stable` attribute input [E0539] fn f1() { } #[stable(feature = "a", since)] //~ ERROR malformed `stable` attribute input [E0539] diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.stderr b/tests/ui/stability-attribute/stability-attribute-sanity.stderr index ae948237d7edf..05c34484b9f86 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity.stderr @@ -1,8 +1,11 @@ -error[E0541]: unknown meta item 'reason' - --> $DIR/stability-attribute-sanity.rs:8:46 +error[E0539]: malformed `stable` attribute input + --> $DIR/stability-attribute-sanity.rs:8:5 | LL | #[stable(feature = "a", since = "4.4.4", reason)] - | ^^^^^^ expected one of `feature`, `since` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^ + | | | + | | valid arguments are `feature` or `since` + | help: must be of the form: `#[stable(feature = "name", since = "version")]` error[E0539]: malformed `stable` attribute input --> $DIR/stability-attribute-sanity.rs:11:5 @@ -138,5 +141,5 @@ LL | #[stable(feature = "a", since = "1.0.0")] error: aborting due to 20 previous errors -Some errors have detailed explanations: E0539, E0541, E0542, E0543, E0544, E0546, E0547, E0549, E0711. +Some errors have detailed explanations: E0539, E0542, E0543, E0544, E0546, E0547, E0549, E0711. For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index eaa26aa3ecafe..05a836b01af5d 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -26,9 +26,9 @@ error[E0539]: malformed `target_feature` attribute input --> $DIR/invalid-attribute.rs:17:1 | LL | #[target_feature = "+sse2"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list + | ^^^^^^^^^^^^^^^^^---------^ + | | | + | | expected this to be a list | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0539]: malformed `target_feature` attribute input diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index 7f0f6a214aae9..383d9108eb908 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -23,15 +23,6 @@ fn upvar() { }; } -fn enum_upvar() { - type T = impl Copy; - let foo: T = Some((1u32, 2u32)); - let x = move || match foo { - None => (), - Some((a, b)) => (), - }; -} - fn r#struct() { #[derive(Copy, Clone)] struct Foo((u32, u32));