diff --git a/Cargo.lock b/Cargo.lock index 395f5a127bd3d..b8c8466ffe9b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.65.0" +version = "0.66.0" dependencies = [ "anyhow", "atty", @@ -4011,6 +4011,7 @@ dependencies = [ "rustc_hir", "rustc_incremental", "rustc_lint", + "rustc_macros", "rustc_metadata", "rustc_middle", "rustc_mir_build", @@ -4359,6 +4360,7 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", + "rustc_target", "tracing", ] diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3d8eee6f5974a..268b0527b1cb2 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1689,7 +1689,7 @@ pub enum StrStyle { #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Lit { /// The original literal token as written in source code. - pub token: token::Lit, + pub token_lit: token::Lit, /// The "semantic" representation of the literal lowered from the original tokens. /// Strings are unescaped, hexadecimal forms are eliminated, etc. /// FIXME: Remove this and only create the semantic representation during lowering to HIR. @@ -1717,7 +1717,7 @@ impl StrLit { StrStyle::Raw(n) => token::StrRaw(n), }; Lit { - token: token::Lit::new(token_kind, self.symbol, self.suffix), + token_lit: token::Lit::new(token_kind, self.symbol, self.suffix), span: self.span, kind: LitKind::Str(self.symbol_unescaped, self.style), } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index bc4f183d9b111..0d114f1366c4d 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -184,13 +184,7 @@ impl MetaItem { } pub fn value_str(&self) -> Option { - match self.kind { - MetaItemKind::NameValue(ref v) => match v.kind { - LitKind::Str(ref s, _) => Some(*s), - _ => None, - }, - _ => None, - } + self.kind.value_str() } pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 9c18f55c03b4d..e6351d89c6c31 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -23,7 +23,7 @@ pub enum LitError { impl LitKind { /// Converts literal token into a semantic literal. - pub fn from_lit_token(lit: token::Lit) -> Result { + pub fn from_token_lit(lit: token::Lit) -> Result { let token::Lit { kind, symbol, suffix } = lit; if suffix.is_some() && !kind.may_have_suffix() { return Err(LitError::InvalidSuffix); @@ -153,7 +153,7 @@ impl LitKind { /// Attempts to recover a token from semantic literal. /// This function is used when the original token doesn't exist (e.g. the literal is created /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn to_lit_token(&self) -> token::Lit { + pub fn to_token_lit(&self) -> token::Lit { let (kind, symbol, suffix) = match *self { LitKind::Str(symbol, ast::StrStyle::Cooked) => { // Don't re-intern unless the escaped string is different. @@ -208,8 +208,8 @@ impl LitKind { impl Lit { /// Converts literal token into an AST literal. - pub fn from_lit_token(token: token::Lit, span: Span) -> Result { - Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span }) + pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result { + Ok(Lit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) } /// Converts arbitrary token into an AST literal. @@ -232,21 +232,21 @@ impl Lit { _ => return Err(LitError::NotLiteral), }; - Lit::from_lit_token(lit, token.span) + Lit::from_token_lit(lit, token.span) } /// Attempts to recover an AST literal from semantic literal. /// This function is used when the original token doesn't exist (e.g. the literal is created /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit { - Lit { token: kind.to_lit_token(), kind, span } + Lit { token_lit: kind.to_token_lit(), kind, span } } /// Losslessly convert an AST literal into a token. pub fn to_token(&self) -> Token { - let kind = match self.token.kind { - token::Bool => token::Ident(self.token.symbol, false), - _ => token::Literal(self.token), + let kind = match self.token_lit.kind { + token::Bool => token::Ident(self.token_lit.symbol, false), + _ => token::Literal(self.token_lit), }; Token::new(kind, self.span) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5f5667ce9055f..1ac1d689efbdb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -927,7 +927,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lit.clone() } else { Lit { - token: token::Lit::new(token::LitKind::Err, kw::Empty, None), + token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), kind: LitKind::Err(kw::Empty), span: DUMMY_SP, } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index c454034efa735..8749a13c5dde1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -372,7 +372,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere fn print_literal(&mut self, lit: &ast::Lit) { self.maybe_print_comment(lit.span.lo()); - self.word(lit.token.to_string()) + self.word(lit.token_lit.to_string()) } fn print_string(&mut self, st: &str, style: ast::StrStyle) { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index a1afec410c1c5..c0f35d122f8e6 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -1,6 +1,5 @@ use rustc_ast as ast; use rustc_ast::{ptr::P, tokenstream::TokenStream}; -use rustc_data_structures::sync::Lrc; use rustc_errors::Applicability; use rustc_expand::base::{self, DummyResult}; @@ -185,5 +184,5 @@ pub fn expand_concat_bytes( return base::MacEager::expr(DummyResult::raw_expr(sp, true)); } let sp = cx.with_def_site_ctxt(sp); - base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(accumulator)))) + base::MacEager::expr(cx.expr_byte_str(sp, accumulator)) } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index d3de10ca4a2e9..467ac34ded942 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -126,9 +126,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { } fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { - let help_msg = match lit.token.kind { - token::Str if rustc_lexer::is_ident(lit.token.symbol.as_str()) => { - format!("try using `#[derive({})]`", lit.token.symbol) + let help_msg = match lit.token_lit.kind { + token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => { + format!("try using `#[derive({})]`", lit.token_lit.symbol) } _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), }; diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index ceef893e862eb..5ab70e441b814 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -52,7 +52,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // We want to make sure we have the ctxt set so that we can use unstable methods let span = cx.with_def_site_ctxt(span); - let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); + let name = cx.expr_str(span, ident.name); let fmt = substr.nonselflike_args[0].clone(); // Struct and tuples are similar enough that we use the same code for both, @@ -89,10 +89,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> for i in 0..fields.len() { let field = &fields[i]; if is_struct { - let name = cx.expr_lit( - field.span, - ast::LitKind::Str(field.name.unwrap().name, ast::StrStyle::Cooked), - ); + let name = cx.expr_str(field.span, field.name.unwrap().name); args.push(name); } // Use an extra indirection to make sure this works for unsized types. @@ -108,10 +105,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> for field in fields { if is_struct { - name_exprs.push(cx.expr_lit( - field.span, - ast::LitKind::Str(field.name.unwrap().name, ast::StrStyle::Cooked), - )); + name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name)); } // Use an extra indirection to make sure this works for unsized types. diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 53c13873b1016..08026c9d35784 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -923,7 +923,7 @@ impl<'a, 'b> Context<'a, 'b> { } // Build the format - let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill)); + let fill = self.ecx.expr_char(sp, fill); let align = |name| { let mut p = Context::rtpath(self.ecx, sym::Alignment); p.push(Ident::new(name, sp)); diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 8bf3a0799b638..d78bbc3c93226 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -216,7 +216,7 @@ pub fn expand_include_bytes( } }; match cx.source_map().load_binary_file(&file) { - Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(bytes.into()))), + Ok(bytes) => base::MacEager::expr(cx.expr_byte_str(sp, bytes)), Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index dbd55590e5c08..2930d09d71f1a 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,7 +15,7 @@ use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{DiagnosticId, FatalError, Handler, Level}; +use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -1740,6 +1740,16 @@ impl SharedEmitter { } } +impl Translate for SharedEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + None + } + + fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { + panic!("shared emitter attempted to translate a diagnostic"); + } +} + impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { let fluent_args = self.to_fluent_args(diag.args()); @@ -1761,14 +1771,6 @@ impl Emitter for SharedEmitter { fn source_map(&self) -> Option<&Lrc> { None } - - fn fluent_bundle(&self) -> Option<&Lrc> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - panic!("shared emitter attempted to translate a diagnostic"); - } } impl SharedEmitterMain { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d563e35f9102d..c8557d172ed43 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -534,7 +534,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let mut non_zst_field = None; for i in 0..receiver.layout.fields.count() { let field = self.operand_field(&receiver, i)?; - if !field.layout.is_zst() { + let zst = + field.layout.is_zst() && field.layout.align.abi.bytes() == 1; + if !zst { assert!( non_zst_field.is_none(), "multiple non-ZST fields in dyn receiver type {}", diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 52952a7932dbc..258780ecaea26 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -56,9 +56,7 @@ cfg_if! { pub fn new(v: T) -> Self { Atomic(Cell::new(v)) } - } - impl Atomic { #[inline] pub fn into_inner(self) -> T { self.0.into_inner() diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl new file mode 100644 index 0000000000000..2c05abd8c0996 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -0,0 +1,6 @@ +interface_ferris_identifier = + Ferris cannot be used as an identifier + .suggestion = try using their name instead + +interface_emoji_identifier = + identifiers cannot contain emoji: `{$ident}` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 9e73a39980927..6ae4dab3a35eb 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -34,6 +34,7 @@ fluent_messages! { builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl", expand => "../locales/en-US/expand.ftl", + interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 3df562c7edac7..b32fc3c719bbd 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -7,6 +7,7 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; +use crate::translation::Translate; use crate::{ CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, @@ -32,6 +33,16 @@ pub struct AnnotateSnippetEmitterWriter { macro_backtrace: bool, } +impl Translate for AnnotateSnippetEmitterWriter { + fn fluent_bundle(&self) -> Option<&Lrc> { + self.fluent_bundle.as_ref() + } + + fn fallback_fluent_bundle(&self) -> &FluentBundle { + &**self.fallback_bundle + } +} + impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, diag: &Diagnostic) { @@ -63,14 +74,6 @@ impl Emitter for AnnotateSnippetEmitterWriter { self.source_map.as_ref() } - fn fluent_bundle(&self) -> Option<&Lrc> { - self.fluent_bundle.as_ref() - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &**self.fallback_bundle - } - fn should_show_explain(&self) -> bool { !self.short_message } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 753e2f07c042e..6c1bfcb9919eb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -14,10 +14,10 @@ use rustc_span::{FileLines, SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; +use crate::translation::Translate; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticArg, DiagnosticId, DiagnosticMessage, FluentBundle, - Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, - SuggestionStyle, + CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler, + LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle, }; use rustc_lint_defs::pluralize; @@ -200,7 +200,7 @@ impl Margin { const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. -pub trait Emitter { +pub trait Emitter: Translate { /// Emit a structured diagnostic. fn emit_diagnostic(&mut self, diag: &Diagnostic); @@ -231,102 +231,6 @@ pub trait Emitter { fn source_map(&self) -> Option<&Lrc>; - /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no - /// language was requested by the user then this will be `None` and `fallback_fluent_bundle` - /// should be used. - fn fluent_bundle(&self) -> Option<&Lrc>; - - /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. - /// Used when the user has not requested a specific language or when a localized diagnostic is - /// unavailable for the requested locale. - fn fallback_fluent_bundle(&self) -> &FluentBundle; - - /// Convert diagnostic arguments (a rustc internal type that exists to implement - /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. - /// - /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then - /// passed around as a reference thereafter. - fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> { - FromIterator::from_iter(args.to_vec().drain(..)) - } - - /// Convert `DiagnosticMessage`s to a string, performing translation if necessary. - fn translate_messages( - &self, - messages: &[(DiagnosticMessage, Style)], - args: &FluentArgs<'_>, - ) -> Cow<'_, str> { - Cow::Owned( - messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::(), - ) - } - - /// Convert a `DiagnosticMessage` to a string, performing translation if necessary. - fn translate_message<'a>( - &'a self, - message: &'a DiagnosticMessage, - args: &'a FluentArgs<'_>, - ) -> Cow<'_, str> { - trace!(?message, ?args); - let (identifier, attr) = match message { - DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg), - DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), - }; - - let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> { - let message = bundle.get_message(&identifier)?; - let value = match attr { - Some(attr) => message.get_attribute(attr)?.value(), - None => message.value()?, - }; - debug!(?message, ?value); - - let mut errs = vec![]; - let translated = bundle.format_pattern(value, Some(&args), &mut errs); - debug!(?translated, ?errs); - Some((translated, errs)) - }; - - self.fluent_bundle() - .and_then(|bundle| translate_with_bundle(bundle)) - // If `translate_with_bundle` returns `None` with the primary bundle, this is likely - // just that the primary bundle doesn't contain the message being translated, so - // proceed to the fallback bundle. - // - // However, when errors are produced from translation, then that means the translation - // is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided). - // - // In debug builds, assert so that compiler devs can spot the broken translation and - // fix it.. - .inspect(|(_, errs)| { - debug_assert!( - errs.is_empty(), - "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", - identifier, - attr, - args, - errs - ); - }) - // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so - // just hide it and try with the fallback bundle. - .filter(|(_, errs)| errs.is_empty()) - .or_else(|| translate_with_bundle(self.fallback_fluent_bundle())) - .map(|(translated, errs)| { - // Always bail out for errors with the fallback bundle. - assert!( - errs.is_empty(), - "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", - identifier, - attr, - args, - errs - ); - translated - }) - .expect("failed to find message in primary or fallback fluent bundles") - } - /// Formats the substitutions of the primary_span /// /// There are a lot of conditions to this method, but in short: @@ -616,11 +520,7 @@ pub trait Emitter { } } -impl Emitter for EmitterWriter { - fn source_map(&self) -> Option<&Lrc> { - self.sm.as_ref() - } - +impl Translate for EmitterWriter { fn fluent_bundle(&self) -> Option<&Lrc> { self.fluent_bundle.as_ref() } @@ -628,6 +528,12 @@ impl Emitter for EmitterWriter { fn fallback_fluent_bundle(&self) -> &FluentBundle { &**self.fallback_bundle } +} + +impl Emitter for EmitterWriter { + fn source_map(&self) -> Option<&Lrc> { + self.sm.as_ref() + } fn emit_diagnostic(&mut self, diag: &Diagnostic) { let fluent_args = self.to_fluent_args(diag.args()); @@ -672,11 +578,7 @@ pub struct SilentEmitter { pub fatal_note: Option, } -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - +impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { None } @@ -684,6 +586,12 @@ impl Emitter for SilentEmitter { fn fallback_fluent_bundle(&self) -> &FluentBundle { panic!("silent emitter attempted to translate message") } +} + +impl Emitter for SilentEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } fn emit_diagnostic(&mut self, d: &Diagnostic) { if d.level == Level::Fatal { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index b8cd334b4c6c6..1680c6accd78c 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -13,6 +13,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use crate::emitter::{Emitter, HumanReadableErrorType}; use crate::registry::Registry; +use crate::translation::Translate; use crate::DiagnosticId; use crate::{ CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic, @@ -122,6 +123,16 @@ impl JsonEmitter { } } +impl Translate for JsonEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + self.fluent_bundle.as_ref() + } + + fn fallback_fluent_bundle(&self) -> &FluentBundle { + &**self.fallback_bundle + } +} + impl Emitter for JsonEmitter { fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) { let data = Diagnostic::from_errors_diagnostic(diag, self); @@ -189,14 +200,6 @@ impl Emitter for JsonEmitter { Some(&self.sm) } - fn fluent_bundle(&self) -> Option<&Lrc> { - self.fluent_bundle.as_ref() - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &**self.fallback_bundle - } - fn should_show_explain(&self) -> bool { !matches!(self.json_rendered, HumanReadableErrorType::Short(_)) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 395bf5aad01b6..6555b93ac0b1b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -58,6 +58,7 @@ mod lock; pub mod registry; mod snippet; mod styled_buffer; +pub mod translation; pub use snippet::Style; diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs new file mode 100644 index 0000000000000..65338f56d9ccb --- /dev/null +++ b/compiler/rustc_errors/src/translation.rs @@ -0,0 +1,103 @@ +use crate::snippet::Style; +use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; +use rustc_data_structures::sync::Lrc; +use rustc_error_messages::FluentArgs; +use std::borrow::Cow; + +pub trait Translate { + /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no + /// language was requested by the user then this will be `None` and `fallback_fluent_bundle` + /// should be used. + fn fluent_bundle(&self) -> Option<&Lrc>; + + /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. + /// Used when the user has not requested a specific language or when a localized diagnostic is + /// unavailable for the requested locale. + fn fallback_fluent_bundle(&self) -> &FluentBundle; + + /// Convert diagnostic arguments (a rustc internal type that exists to implement + /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. + /// + /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then + /// passed around as a reference thereafter. + fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> { + FromIterator::from_iter(args.to_vec().drain(..)) + } + + /// Convert `DiagnosticMessage`s to a string, performing translation if necessary. + fn translate_messages( + &self, + messages: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, + ) -> Cow<'_, str> { + Cow::Owned( + messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::(), + ) + } + + /// Convert a `DiagnosticMessage` to a string, performing translation if necessary. + fn translate_message<'a>( + &'a self, + message: &'a DiagnosticMessage, + args: &'a FluentArgs<'_>, + ) -> Cow<'_, str> { + trace!(?message, ?args); + let (identifier, attr) = match message { + DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg), + DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + }; + + let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> { + let message = bundle.get_message(&identifier)?; + let value = match attr { + Some(attr) => message.get_attribute(attr)?.value(), + None => message.value()?, + }; + debug!(?message, ?value); + + let mut errs = vec![]; + let translated = bundle.format_pattern(value, Some(&args), &mut errs); + debug!(?translated, ?errs); + Some((translated, errs)) + }; + + self.fluent_bundle() + .and_then(|bundle| translate_with_bundle(bundle)) + // If `translate_with_bundle` returns `None` with the primary bundle, this is likely + // just that the primary bundle doesn't contain the message being translated, so + // proceed to the fallback bundle. + // + // However, when errors are produced from translation, then that means the translation + // is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided). + // + // In debug builds, assert so that compiler devs can spot the broken translation and + // fix it.. + .inspect(|(_, errs)| { + debug_assert!( + errs.is_empty(), + "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", + identifier, + attr, + args, + errs + ); + }) + // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so + // just hide it and try with the fallback bundle. + .filter(|(_, errs)| errs.is_empty()) + .or_else(|| translate_with_bundle(self.fallback_fluent_bundle())) + .map(|(translated, errs)| { + // Always bail out for errors with the fallback bundle. + assert!( + errs.is_empty(), + "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", + identifier, + attr, + args, + errs + ); + translated + }) + .expect("failed to find message in primary or fallback fluent bundles") + } +} diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index fa3e2a4a5b81c..b971a63ec8977 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -3,6 +3,7 @@ use crate::base::ExtCtxt; use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; +use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -330,23 +331,38 @@ impl<'a> ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - pub fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P { + fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P { let lit = ast::Lit::from_lit_kind(lit_kind, span); self.expr(span, ast::ExprKind::Lit(lit)) } + pub fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit( span, ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), ) } + pub fn expr_u32(&self, sp: Span, u: u32) -> P { self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32))) } + pub fn expr_bool(&self, sp: Span, value: bool) -> P { self.expr_lit(sp, ast::LitKind::Bool(value)) } + pub fn expr_str(&self, sp: Span, s: Symbol) -> P { + self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) + } + + pub fn expr_char(&self, sp: Span, ch: char) -> P { + self.expr_lit(sp, ast::LitKind::Char(ch)) + } + + pub fn expr_byte_str(&self, sp: Span, bytes: Vec) -> P { + self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes))) + } + /// `[expr1, expr2, ...]` pub fn expr_array(&self, sp: Span, exprs: Vec>) -> P { self.expr(sp, ast::ExprKind::Array(exprs)) @@ -357,10 +373,6 @@ impl<'a> ExtCtxt<'a> { self.expr_addr_of(sp, self.expr_array(sp, exprs)) } - pub fn expr_str(&self, sp: Span, s: Symbol) -> P { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) - } - pub fn expr_cast(&self, sp: Span, expr: P, ty: P) -> P { self.expr(sp, ast::ExprKind::Cast(expr, ty)) } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index fc808401a5eb1..99fe474541e9d 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -112,7 +112,7 @@ fn parse_depth<'sess>( "meta-variable expression depth must be a literal" )); }; - if let Ok(lit_kind) = LitKind::from_lit_token(*lit) + if let Ok(lit_kind) = LitKind::from_token_lit(*lit) && let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind && let Ok(n_usize) = usize::try_from(n_u128) { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 7d9a4aed0bf54..beb33c05913cf 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -486,20 +486,26 @@ impl server::TokenStream for Rustc<'_, '_> { // We don't use `TokenStream::from_ast` as the tokenstream currently cannot // be recovered in the general case. match &expr.kind { - ast::ExprKind::Lit(l) if l.token.kind == token::Bool => Ok( - tokenstream::TokenStream::token_alone(token::Ident(l.token.symbol, false), l.span), - ), + ast::ExprKind::Lit(l) if l.token_lit.kind == token::Bool => { + Ok(tokenstream::TokenStream::token_alone( + token::Ident(l.token_lit.symbol, false), + l.span, + )) + } ast::ExprKind::Lit(l) => { - Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token), l.span)) + Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token_lit), l.span)) } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { - ast::ExprKind::Lit(l) => match l.token { + ast::ExprKind::Lit(l) => match l.token_lit { token::Lit { kind: token::Integer | token::Float, .. } => { Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span), - tokenstream::TokenTree::token_alone(token::Literal(l.token), l.span), + tokenstream::TokenTree::token_alone( + token::Literal(l.token_lit), + l.span, + ), ])) } _ => Err(()), diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e6fcb84730ea4..0f754dddbec84 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1247,7 +1247,7 @@ impl<'a> State<'a> { fn print_literal(&mut self, lit: &hir::Lit) { self.maybe_print_comment(lit.span.lo()); - self.word(lit.node.to_lit_token().to_string()) + self.word(lit.node.to_token_lit().to_string()) } fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) { diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 1ecbc876c8d8a..da4002d09ad02 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -17,6 +17,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_expand = { path = "../rustc_expand" } +rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8f0835917861a..e00d0b7d0d82f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -8,11 +8,12 @@ use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult}; +use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::StableCrateId; use rustc_hir::definitions::Definitions; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; +use rustc_macros::SessionDiagnostic; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -30,7 +31,7 @@ use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::FileName; +use rustc_span::{FileName, Span}; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tracing::{info, warn}; @@ -263,6 +264,23 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { } } +#[derive(SessionDiagnostic)] +#[error(interface::ferris_identifier)] +struct FerrisIdentifier { + #[primary_span] + spans: Vec, + #[suggestion(code = "ferris", applicability = "maybe-incorrect")] + first_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(interface::emoji_identifier)] +struct EmojiIdentifier { + #[primary_span] + spans: Vec, + ident: Symbol, +} + /// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the @@ -443,23 +461,9 @@ pub fn configure_and_expand( spans.sort(); if ident == sym::ferris { let first_span = spans[0]; - sess.diagnostic() - .struct_span_err( - MultiSpan::from(spans), - "Ferris cannot be used as an identifier", - ) - .span_suggestion( - first_span, - "try using their name instead", - "ferris", - Applicability::MaybeIncorrect, - ) - .emit(); + sess.emit_err(FerrisIdentifier { spans, first_span }); } else { - sess.diagnostic().span_err( - MultiSpan::from(spans), - &format!("identifiers cannot contain emoji: `{}`", ident), - ); + sess.emit_err(EmojiIdentifier { spans, ident }); } } }); diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index fe2712525eea5..8f22221324a6e 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -120,8 +120,8 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString` let (text, span, padding) = match &expr.kind { - ast::ExprKind::Lit(ast::Lit { token, kind, span }) => { - let text = token.symbol; + ast::ExprKind::Lit(ast::Lit { token_lit, kind, span }) => { + let text = token_lit.symbol; if !contains_text_flow_control_chars(text.as_str()) { return; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cfc75f673c8f5..8a727d9a1825a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -770,6 +770,7 @@ rustc_queries! { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern + cycle_delay_bug } /// Performs lint checking for the module. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9d6d632c2e89a..c824566c35ff4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1750,8 +1750,8 @@ impl<'a> Parser<'a> { Some(lit) => match lit.kind { ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { style, - symbol: lit.token.symbol, - suffix: lit.token.suffix, + symbol: lit.token_lit.symbol, + suffix: lit.token_lit.suffix, span: lit.span, symbol_unescaped, }), @@ -1828,7 +1828,7 @@ impl<'a> Parser<'a> { let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let symbol = Symbol::intern(&suffixless_lit.to_string()); let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!())) + Some(Lit::from_token_lit(lit, span).unwrap_or_else(|_| unreachable!())) } } } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 5673bb83b15f4..c37ae4f32536b 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -20,6 +20,7 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } tracing = "0.1" [features] diff --git a/compiler/rustc_query_impl/src/values.rs b/compiler/rustc_query_impl/src/values.rs index 718a2971c403d..0ed48f8d4a051 100644 --- a/compiler/rustc_query_impl/src/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -43,3 +43,23 @@ impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> { } } } + +impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> { + fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self { + let err = tcx.ty_error(); + // FIXME(compiler-errors): It would be nice if we could get the + // query key, so we could at least generate a fn signature that + // has the right arity. + let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig( + [].into_iter(), + err, + false, + rustc_hir::Unsafety::Normal, + rustc_target::spec::abi::Abi::Rust, + )); + + // SAFETY: This is never called when `Self` is not `ty::Binder<'tcx, ty::FnSig<'tcx>>`. + // FIXME: Represent the above fact in the trait system somehow. + unsafe { std::mem::transmute::, ty::Binder<'_, ty::FnSig<'_>>>(fn_sig) } + } +} diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs index a76ffe808c3b2..797dfe52bd149 100644 --- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs @@ -38,7 +38,9 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Ld, linker: Some("arm-none-eabi-ld".into()), asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",], - features: "+soft-float,+strict-align".into(), + // Force-enable 32-bit atomics, which allows the use of atomic load/store only. + // The resulting atomics are ABI incompatible with atomics backed by libatomic. + features: "+soft-float,+strict-align,+atomics-32".into(), main_needs_argc_argv: false, atomic_cas: false, has_thumb_interworking: true, diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs index 7125d141af7f5..bdaaed8b5d0e8 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs @@ -47,7 +47,9 @@ pub fn target() -> Target { asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",], // minimum extra features, these cannot be disabled via -C - features: "+soft-float,+strict-align".into(), + // Also force-enable 32-bit atomics, which allows the use of atomic load/store only. + // The resulting atomics are ABI incompatible with atomics backed by libatomic. + features: "+soft-float,+strict-align,+atomics-32".into(), panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9bb41b900b89a..985600d9ebcc2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -404,12 +404,12 @@ fn resolve_negative_obligation<'cx, 'tcx>( pub fn trait_ref_is_knowable<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, -) -> Option { +) -> Result<(), Conflict> { debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref); if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() { // A downstream or cousin crate is allowed to implement some // substitution of this trait-ref. - return Some(Conflict::Downstream); + return Err(Conflict::Downstream); } if trait_ref_is_local_or_fundamental(tcx, trait_ref) { @@ -418,7 +418,7 @@ pub fn trait_ref_is_knowable<'tcx>( // allowed to implement a substitution of this trait ref, which // means impls could only come from dependencies of this crate, // which we already know about. - return None; + return Ok(()); } // This is a remote non-fundamental trait, so if another crate @@ -431,10 +431,10 @@ pub fn trait_ref_is_knowable<'tcx>( // we are an owner. if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() { debug!("trait_ref_is_knowable: orphan check passed"); - None + Ok(()) } else { debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned"); - Some(Conflict::Upstream) + Err(Conflict::Upstream) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 50e9b95a445fd..d67bd6292b434 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -75,7 +75,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { - if let Some(conflict) = self.is_knowable(stack) { + if let Err(conflict) = self.is_knowable(stack) { debug!("coherence stage: not knowable"); if self.intercrate_ambiguity_causes.is_some() { debug!("evaluate_stack: intercrate_ambiguity_causes is some"); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c01ac19799106..46b50dd92f1ef 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1265,11 +1265,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(candidate)) } - fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option { + fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> { debug!("is_knowable(intercrate={:?})", self.intercrate); if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative { - return None; + return Ok(()); } let obligation = &stack.obligation; diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index c82c819169d3a..5ff62f36b4527 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -561,16 +561,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We just want to check sizedness, so instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); + let arg_span = args.get(i).map(|a| a.span); + let span = arg_span.unwrap_or(expr.span); let input = self.replace_bound_vars_with_fresh_vars( span, infer::LateBoundRegionConversionTime::FnCall, fn_sig.input(i), ); - self.require_type_is_sized_deferred( - input, + self.require_type_is_sized( + self.normalize_associated_types_in(span, input), span, - traits::SizedArgumentType(None), + traits::SizedArgumentType(arg_span), ); } } @@ -585,7 +586,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::LateBoundRegionConversionTime::FnCall, fn_sig.output(), ); - self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + self.require_type_is_sized( + self.normalize_associated_types_in(expr.span, output), + expr.span, + traits::SizedReturnType, + ); } // We always require that the type provided as the value for diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 3a8093345119f..1d9d04ceec0d7 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -442,17 +442,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn require_type_is_sized_deferred( - &self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>, - ) { - if !ty.references_error() { - self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); - } - } - pub fn register_bound( &self, ty: Ty<'tcx>, diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index cd152eb97f1bf..f3115fc5c0232 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -35,11 +35,6 @@ pub struct Inherited<'a, 'tcx> { pub(super) fulfillment_cx: RefCell>>, - // Some additional `Sized` obligations badly affect type inference. - // These obligations are added in a later stage of typeck. - pub(super) deferred_sized_obligations: - RefCell, Span, traits::ObligationCauseCode<'tcx>)>>, - // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -117,7 +112,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { infcx, fulfillment_cx: RefCell::new(>::new(tcx)), locals: RefCell::new(Default::default()), - deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_transmute_checks: RefCell::new(Vec::new()), diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 1b50209ee64cc..dfbef544b1d28 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -467,11 +467,6 @@ fn typeck_with_fallback<'tcx>( fcx.resolve_rvalue_scopes(def_id.to_def_id()); fcx.resolve_generator_interiors(def_id.to_def_id()); - for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { - let ty = fcx.normalize_ty(span, ty); - fcx.require_type_is_sized(ty, span, code); - } - fcx.select_all_obligations_or_error(); if !fcx.infcx.is_tainted_by_errors() { diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 6548ad2e514fb..23c46f1a74a31 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -394,7 +394,7 @@ impl f32 { /// Not a Number (NaN). /// - /// Note that IEEE-745 doesn't define just a single NaN value; + /// Note that IEEE-754 doesn't define just a single NaN value; /// a plethora of bit patterns are considered to be NaN. /// Furthermore, the standard makes a difference /// between a "signaling" and a "quiet" NaN, @@ -632,7 +632,7 @@ impl f32 { } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any + /// positive sign bit and positive infinity. Note that IEEE-754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. @@ -654,7 +654,7 @@ impl f32 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any + /// negative sign bit and negative infinity. Note that IEEE-754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 75c92c2f8834a..b5c8241d2943d 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -393,7 +393,7 @@ impl f64 { /// Not a Number (NaN). /// - /// Note that IEEE-745 doesn't define just a single NaN value; + /// Note that IEEE-754 doesn't define just a single NaN value; /// a plethora of bit patterns are considered to be NaN. /// Furthermore, the standard makes a difference /// between a "signaling" and a "quiet" NaN, @@ -624,7 +624,7 @@ impl f64 { } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any + /// positive sign bit and positive infinity. Note that IEEE-754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. @@ -655,7 +655,7 @@ impl f64 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any + /// negative sign bit and negative infinity. Note that IEEE-754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. diff --git a/library/unwind/build.rs b/library/unwind/build.rs index 126e41d1e2015..31af390253b6f 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs @@ -2,8 +2,14 @@ use std::env; fn main() { println!("cargo:rerun-if-changed=build.rs"); - let target = env::var("TARGET").expect("TARGET was not set"); + println!("cargo:rerun-if-env-changed=CARGO_CFG_MIRI"); + + if env::var_os("CARGO_CFG_MIRI").is_some() { + // Miri doesn't need the linker flags or a libunwind build. + return; + } + let target = env::var("TARGET").expect("TARGET was not set"); if target.contains("android") { let build = cc::Build::new(); diff --git a/src/doc/book b/src/doc/book index 36383b4da21db..42ca0ef484fcc 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 36383b4da21dbd0a0781473bc8ad7ef0ed1b6751 +Subproject commit 42ca0ef484fcc8437a0682cee23abe4b7c407d52 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index c55611dd6c58b..6038be9d37d72 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit c55611dd6c58bdeb52423b5c52fd0f3c93615ba8 +Subproject commit 6038be9d37d7251c966b486154af621d1794d7af diff --git a/src/doc/nomicon b/src/doc/nomicon index 8d1e4dccf7111..8e6aa3448515a 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 8d1e4dccf71114ff56f328f671f2026d8e6b62a2 +Subproject commit 8e6aa3448515a0654e347b5e2510f1d4bc4d5a64 diff --git a/src/doc/reference b/src/doc/reference index f3d3953bf3b15..e647eb102890e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit f3d3953bf3b158d596c96d55ce5366f9f3f972e9 +Subproject commit e647eb102890e8927f488bea12672b079eff8d9d diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ee342dc91e1ba..03301f8ae55fa 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ee342dc91e1ba1bb1e1f1318f84bbe3bfac04798 +Subproject commit 03301f8ae55fa6f20f7ea152a517598e6db2cdb7 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 04f3cf0bb2f5a..d3daa1f28e169 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 04f3cf0bb2f5a6ee2bfc4b1a6a6cd8c11d1c5531 +Subproject commit d3daa1f28e169087becbc5e2b49ac91ca0405a44 diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 0172ef5700b62..381ac7a5deef1 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,7 +1,8 @@ //! Validates syntax inside Rust code blocks (\`\`\`rust). use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{ - emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder, + emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler, + LazyFallbackBundle, LintDiagnosticBuilder, }; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; @@ -181,6 +182,16 @@ struct BufferEmitter { fallback_bundle: LazyFallbackBundle, } +impl Translate for BufferEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + None + } + + fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { + &**self.fallback_bundle + } +} + impl Emitter for BufferEmitter { fn emit_diagnostic(&mut self, diag: &Diagnostic) { let mut buffer = self.buffer.borrow_mut(); @@ -194,12 +205,4 @@ impl Emitter for BufferEmitter { fn source_map(&self) -> Option<&Lrc> { None } - - fn fluent_bundle(&self) -> Option<&Lrc> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - &**self.fallback_bundle - } } diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs index 5ff7b19d8945e..53358b183cbf5 100644 --- a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs +++ b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs @@ -9,7 +9,6 @@ where use std::convert::TryFrom; <[T; N.get()]>::try_from(()) //~^ error: the trait bound - //~| error: the trait bound //~| error: mismatched types } diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index b0e717d8a86ba..9ff1f60c0d5c7 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -4,27 +4,28 @@ // @is nested.json "$.crate_version" \"1.0.0\" // @is - "$.index[*][?(@.name=='nested')].kind" \"module\" // @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true -// @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1 + +// @set l1_id = - "$.index[*][?(@.name=='l1')].id" +// @ismany - "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id // @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\" // @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false -// @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2 pub mod l1 { - // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\" // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false - // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1 // @set l3_id = - "$.index[*][?(@.name=='l3')].id" - // @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id pub mod l3 { // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\" // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" // @set l4_id = - "$.index[*][?(@.name=='L4')].id" - // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id + // @ismany - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; } // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\" // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false + // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id + // @set l4_use_id = - "$.index[*][?(@.inner.source=='l3::L4')].id" pub use l3::L4; } +// @ismany - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs index ba1cfd8a0b577..4fe25904423ed 100644 --- a/src/test/rustdoc-json/reexport/glob_extern.rs +++ b/src/test/rustdoc-json/reexport/glob_extern.rs @@ -4,15 +4,20 @@ #![feature(no_core)] // @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\" -// @is glob_extern.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" +// @is - "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" mod mod1 { extern "C" { - // @has - "$.index[*][?(@.name=='public_fn')].id" + // @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id" pub fn public_fn(); // @!has - "$.index[*][?(@.name=='private_fn')]" fn private_fn(); } + // @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id + // @set mod1_id = - "$.index[*][?(@.name=='mod1')].id" } // @is - "$.index[*][?(@.kind=='import')].inner.glob" true +// @is - "$.index[*][?(@.kind=='import')].inner.id" $mod1_id +// @set use_id = - "$.index[*][?(@.kind=='import')].id" +// @ismany - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id pub use mod1::*; diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs index e6a44748c25fb..04460a817f130 100644 --- a/src/test/rustdoc-json/reexport/glob_private.rs +++ b/src/test/rustdoc-json/reexport/glob_private.rs @@ -16,7 +16,7 @@ mod mod1 { struct Mod2Private; } - // @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]" + // @set mod2_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id" pub use self::mod2::*; // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id" @@ -25,8 +25,9 @@ mod mod1 { struct Mod1Private; } -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]" +// @set mod1_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id" pub use mod1::*; -// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id -// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id +// @ismany - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id +// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id +// @ismany - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs index 2daadf7620ca0..09302ee3acb2d 100644 --- a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -3,7 +3,7 @@ pub mod foo { // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id" - // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id + // @ismany - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id pub struct Bar; } @@ -15,6 +15,6 @@ pub use foo::Bar; pub mod baz { // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id" // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id - // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id + // @ismany - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id pub use crate::foo::Bar; } diff --git a/src/test/rustdoc-json/reexport/macro.rs b/src/test/rustdoc-json/reexport/macro.rs index b86614ffbad68..0959736f30988 100644 --- a/src/test/rustdoc-json/reexport/macro.rs +++ b/src/test/rustdoc-json/reexport/macro.rs @@ -3,15 +3,13 @@ #![no_core] #![feature(no_core)] -// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2 - // @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id" -// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id #[macro_export] macro_rules! repro { () => {}; } // @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id" -// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id pub use crate::repro as repro2; + +// @ismany macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id diff --git a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs index 327b0f45fdd54..a76d352b28ba4 100644 --- a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs @@ -1,18 +1,28 @@ // aux-build:pub-struct.rs +// ignore-tidy-linelength -// Test for the ICE in rust/83057 -// Am external type re-exported with different attributes shouldn't cause an error +// Test for the ICE in https://github.com/rust-lang/rust/issues/83057 +// An external type re-exported with different attributes shouldn't cause an error #![no_core] #![feature(no_core)] extern crate pub_struct as foo; - #[doc(inline)] + +// @set crate_use_id = private_twice_one_inline.json "$.index[*][?(@.docs=='Hack A')].id" +// @set foo_id = - "$.index[*][?(@.docs=='Hack A')].inner.id" +/// Hack A pub use foo::Foo; +// @set bar_id = - "$.index[*][?(@.name=='bar')].id" pub mod bar { + // @is - "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id + // @set bar_use_id = - "$.index[*][?(@.docs=='Hack B')].id" + // @ismany - "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id + /// Hack B pub use foo::Foo; } -// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2 +// @ismany - "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id +// @ismany - "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs index 36d6a50d385a2..cd8212cf34419 100644 --- a/src/test/rustdoc-json/reexport/private_two_names.rs +++ b/src/test/rustdoc-json/reexport/private_two_names.rs @@ -1,4 +1,6 @@ -// Test for the ICE in rust/83720 +// ignore-tidy-linelength + +// Test for the ICE in https://github.com/rust-lang/rust/issues/83720 // A pub-in-private type re-exported under two different names shouldn't cause an error #![no_core] @@ -7,11 +9,15 @@ // @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\" // @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true" mod style { - // @has - "$.index[*](?(@.name=='Color'))" + // @set color_struct_id = - "$.index[*][?(@.kind=='struct' && @.name=='Color')].id" pub struct Color; } -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]" +// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id +// @set color_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id" pub use style::Color; -// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]" +// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id +// @set colour_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id" pub use style::Color as Colour; + +// @ismany - "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs index 2dd438d223058..d41556974b43b 100644 --- a/src/test/rustdoc-json/reexport/rename_public.rs +++ b/src/test/rustdoc-json/reexport/rename_public.rs @@ -4,14 +4,14 @@ #![feature(no_core)] // @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id" -// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id pub mod inner { // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } // @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id" // @!has - "$.index[*][?(@.inner.name=='Public')]" -// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id // @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\" pub use inner::Public as NewName; + +// @ismany - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id diff --git a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index eedddd6a7bb48..1d76c7e139bdb 100644 --- a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // Regression test for . #![feature(no_core)] @@ -5,11 +7,17 @@ #![no_core] // @has same_type_reexported_more_than_once.json -// @has - "$.index[*][?(@.name=='Trait')]" -pub use inner::Trait; -// @has - "$.index[*].inner[?(@.name=='Reexport')].id" -pub use inner::Trait as Reexport; mod inner { + // @set trait_id = - "$.index[*][?(@.name=='Trait')].id" pub trait Trait {} } + +// @set export_id = - "$.index[*][?(@.inner.name=='Trait')].id" +// @is - "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id +pub use inner::Trait; +// @set reexport_id = - "$.index[*][?(@.inner.name=='Reexport')].id" +// @is - "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id +pub use inner::Trait as Reexport; + +// @ismany - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs index 5ec13e403aef6..55523bcd1deef 100644 --- a/src/test/rustdoc-json/reexport/simple_private.rs +++ b/src/test/rustdoc-json/reexport/simple_private.rs @@ -10,6 +10,8 @@ mod inner { } // @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\" +// @set use_id = - "$.index[*][?(@.kind=='import')].id" pub use inner::Public; -// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id +// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id +// @ismany - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs index 2e4de301f6f11..a3156a2b33a8e 100644 --- a/src/test/rustdoc-json/reexport/simple_public.rs +++ b/src/test/rustdoc-json/reexport/simple_public.rs @@ -4,15 +4,15 @@ #![feature(no_core)] // @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id" -// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id pub mod inner { // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } // @set import_id = - "$.index[*][?(@.inner.name=='Public')].id" -// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id // @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\" pub use inner::Public; + +// @ismany - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs index e0d1e9649a0aa..fd49a0890c0df 100644 --- a/src/test/rustdoc-json/type/fn_lifetime.rs +++ b/src/test/rustdoc-json/type/fn_lifetime.rs @@ -2,8 +2,7 @@ // @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\" -// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" +// @ismany - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" // @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime" // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0 // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0 diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index c37d469890c08..66f1ab726922d 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -33,7 +33,9 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:14 | LL | f1(2u32, 4u32); - | ^^^^ the trait `Foo` is not implemented for `u32` + | -- ^^^^ the trait `Foo` is not implemented for `u32` + | | + | required by a bound introduced by this call | = help: the trait `Foo` is implemented for `i32` diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr index 0f7520ef7f8a9..0557340f792fd 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -15,11 +15,16 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known --> $DIR/feature-gate-unsized_fn_params.rs:24:9 | LL | foo(*x); - | ^^ doesn't have a size known at compile-time + | --- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` - = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | foo(&*x); + | + error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/issue-28098.rs b/src/test/ui/iterators/issue-28098.rs index 62a90d90d12de..c4addaccefc10 100644 --- a/src/test/ui/iterators/issue-28098.rs +++ b/src/test/ui/iterators/issue-28098.rs @@ -1,7 +1,6 @@ fn main() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator @@ -17,7 +16,6 @@ pub fn other() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator diff --git a/src/test/ui/iterators/issue-28098.stderr b/src/test/ui/iterators/issue-28098.stderr index 3beb9929244bf..e7128248f9341 100644 --- a/src/test/ui/iterators/issue-28098.stderr +++ b/src/test/ui/iterators/issue-28098.stderr @@ -9,7 +9,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:6:14 + --> $DIR/issue-28098.rs:5:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -18,7 +18,7 @@ LL | for _ in false {} = note: required because of the requirements on the impl of `IntoIterator` for `bool` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:9:28 + --> $DIR/issue-28098.rs:8:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -28,15 +28,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:2:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:18:28 + --> $DIR/issue-28098.rs:17:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -46,7 +38,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:22:28 + --> $DIR/issue-28098.rs:20:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -56,7 +48,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:25:14 + --> $DIR/issue-28098.rs:23:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -64,14 +56,6 @@ LL | for _ in false {} = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:18:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs index b74957ebcd406..79c40f650db81 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.rs +++ b/src/test/ui/on-unimplemented/multiple-impls.rs @@ -32,11 +32,8 @@ impl Index> for [i32] { fn main() { Index::index(&[] as &[i32], 2u32); //~^ ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 06e1a222af881..6e3601d7bf4b5 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -12,7 +12,7 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:36:18 + --> $DIR/multiple-impls.rs:35:18 | LL | Index::index(&[] as &[i32], Foo(2u32)); | ------------ ^^^^^^^^^^^^^ on impl for Foo @@ -25,7 +25,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:39:18 + --> $DIR/multiple-impls.rs:37:18 | LL | Index::index(&[] as &[i32], Bar(2u32)); | ------------ ^^^^^^^^^^^^^ on impl for Bar @@ -37,39 +37,6 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/multiple-impls.rs:33:5 - | -LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^ trait message - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:36:5 - | -LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^ on impl for Foo - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:39:5 - | -LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^ on impl for Bar - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs index ab3e67d01fe44..b03e1f7c6a8df 100644 --- a/src/test/ui/on-unimplemented/on-impl.rs +++ b/src/test/ui/on-unimplemented/on-impl.rs @@ -21,5 +21,4 @@ impl Index for [i32] { fn main() { Index::::index(&[1, 2, 3] as &[i32], 2u32); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 769a3d77a5726..396c062cfe2ac 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -9,15 +9,6 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is implemented for `[i32]` -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/on-impl.rs:22:5 - | -LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the trait `Index` is implemented for `[i32]` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/return-cycle-2.rs b/src/test/ui/suggestions/return-cycle-2.rs new file mode 100644 index 0000000000000..d6d24be1b8dc4 --- /dev/null +++ b/src/test/ui/suggestions/return-cycle-2.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomData; + +struct Token(PhantomData); + +impl Token { + fn as_ref(_: i32, _: i32) -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + //~| NOTE not allowed in type signatures + //~| HELP replace with the correct return type + Token(PhantomData::<&T>) + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/return-cycle-2.stderr b/src/test/ui/suggestions/return-cycle-2.stderr new file mode 100644 index 0000000000000..3a1a0f7f4f543 --- /dev/null +++ b/src/test/ui/suggestions/return-cycle-2.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/return-cycle-2.rs:6:34 + | +LL | fn as_ref(_: i32, _: i32) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Token<&'static T>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/suggestions/return-cycle.rs b/src/test/ui/suggestions/return-cycle.rs new file mode 100644 index 0000000000000..60b80e35a20b8 --- /dev/null +++ b/src/test/ui/suggestions/return-cycle.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomData; + +struct Token(PhantomData); + +impl Token { + fn new() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + //~| NOTE not allowed in type signatures + //~| HELP replace with the correct return type + Token(PhantomData::<()>) + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/return-cycle.stderr b/src/test/ui/suggestions/return-cycle.stderr new file mode 100644 index 0000000000000..63fa9e040874d --- /dev/null +++ b/src/test/ui/suggestions/return-cycle.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/return-cycle.rs:6:17 + | +LL | fn new() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Token<()>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr index 71bbdf5dec769..d7af558eef42a 100644 --- a/src/test/ui/unsized/issue-30355.stderr +++ b/src/test/ui/unsized/issue-30355.stderr @@ -2,11 +2,16 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation --> $DIR/issue-30355.rs:5:8 | LL | &X(*Y) - | ^^ doesn't have a size known at compile-time + | - ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[u8]` - = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | &X(&*Y) + | + error: aborting due to previous error diff --git a/src/tools/cargo b/src/tools/cargo index efd4ca3dc0b89..9809f8ff33c2b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit efd4ca3dc0b89929dc8c5f5c023d25978d76cb61 +Subproject commit 9809f8ff33c2b998919fd0432c626f0f7323697a diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index 6ad6837f0e350..bffbf20b4d289 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -57,10 +57,10 @@ impl EarlyLintPass for OctalEscapes { } if let ExprKind::Lit(lit) = &expr.kind { - if matches!(lit.token.kind, LitKind::Str) { - check_lit(cx, &lit.token, lit.span, true); - } else if matches!(lit.token.kind, LitKind::ByteStr) { - check_lit(cx, &lit.token, lit.span, false); + if matches!(lit.token_lit.kind, LitKind::Str) { + check_lit(cx, &lit.token_lit, lit.span, true); + } else if matches!(lit.token_lit.kind, LitKind::ByteStr) { + check_lit(cx, &lit.token_lit, lit.span, false); } } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 32718200c0b3a..fa2383066f3f6 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -589,12 +589,12 @@ impl Write { }, }; - let replacement: String = match lit.token.kind { + let replacement: String = match lit.token_lit.kind { LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => { - lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}") + lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}") }, LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => { - lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}") + lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}") }, LitKind::StrRaw(_) | LitKind::Str @@ -603,7 +603,7 @@ impl Write { | LitKind::Integer | LitKind::Float | LitKind::Err => continue, - LitKind::Byte | LitKind::Char => match lit.token.symbol.as_str() { + LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() { "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"", "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue, "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\", @@ -614,7 +614,7 @@ impl Write { x => x, } .into(), - LitKind::Bool => lit.token.symbol.as_str().deref().into(), + LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(), }; if !fmt_spans.is_empty() { diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index c44624666465e..022f7eb8e02d0 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -50,6 +50,7 @@ pub enum CommandKind { Has, Count, Is, + IsMany, Set, } @@ -57,6 +58,7 @@ impl CommandKind { fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool { let count = match self { CommandKind::Has => (1..=3).contains(&args.len()), + CommandKind::IsMany => args.len() >= 3, CommandKind::Count | CommandKind::Is => 3 == args.len(), CommandKind::Set => 4 == args.len(), }; @@ -89,6 +91,7 @@ impl fmt::Display for CommandKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let text = match self { CommandKind::Has => "has", + CommandKind::IsMany => "ismany", CommandKind::Count => "count", CommandKind::Is => "is", CommandKind::Set => "set", @@ -137,6 +140,7 @@ fn get_commands(template: &str) -> Result, ()> { "has" => CommandKind::Has, "count" => CommandKind::Count, "is" => CommandKind::Is, + "ismany" => CommandKind::IsMany, "set" => CommandKind::Set, _ => { print_err(&format!("Unrecognized command name `@{}`", cmd), lineno); @@ -227,6 +231,44 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { _ => unreachable!(), } } + CommandKind::IsMany => { + // @ismany ... + let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] { + (path, query, values) + } else { + unreachable!("Checked in CommandKind::validate") + }; + let val = cache.get_value(path)?; + let got_values = select(&val, &query).unwrap(); + assert!(!command.negated, "`@!ismany` is not supported"); + + // Serde json doesn't implement Ord or Hash for Value, so we must + // use a Vec here. While in theory that makes setwize equality + // O(n^2), in practice n will never be large enought to matter. + let expected_values = + values.iter().map(|v| string_to_value(v, cache)).collect::>(); + if expected_values.len() != got_values.len() { + return Err(CkError::FailedCheck( + format!( + "Expected {} values, but `{}` matched to {} values ({:?})", + expected_values.len(), + query, + got_values.len(), + got_values + ), + command, + )); + }; + for got_value in got_values { + if !expected_values.iter().any(|exp| &**exp == got_value) { + return Err(CkError::FailedCheck( + format!("`{}` has match {:?}, which was not expected", query, got_value), + command, + )); + } + } + true + } CommandKind::Count => { // @count = Check that the jsonpath matches exactly [count] times assert_eq!(command.args.len(), 3); diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index a7b73ba78c59e..3105882e2d308 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -79,7 +79,7 @@ pub(crate) fn format_expr( if let Some(expr_rw) = rewrite_literal(context, l, shape) { Some(expr_rw) } else { - if let LitKind::StrRaw(_) = l.token.kind { + if let LitKind::StrRaw(_) = l.token_lit.kind { Some(context.snippet(l.span).trim().into()) } else { None @@ -1226,7 +1226,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option { let span = lit.span; - let symbol = lit.token.symbol.as_str(); + let symbol = lit.token_lit.symbol.as_str(); if let Some(symbol_stripped) = symbol.strip_prefix("0x") { let hex_lit = match context.config.hex_literal_case() { @@ -1239,7 +1239,9 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) - format!( "0x{}{}", hex_lit, - lit.token.suffix.map_or(String::new(), |s| s.to_string()) + lit.token_lit + .suffix + .map_or(String::new(), |s| s.to_string()) ), context.config.max_width(), shape, diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 23db542191036..6efeee98fea6c 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ @@ -28,19 +29,24 @@ pub(crate) struct ParseSess { /// Emitter which discards every error. struct SilentEmitter; -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} +impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { None } + fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { panic!("silent emitter attempted to translate a diagnostic"); } } +impl Emitter for SilentEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + + fn emit_diagnostic(&mut self, _db: &Diagnostic) {} +} + fn silent_emitter() -> Box { Box::new(SilentEmitter {}) } @@ -62,10 +68,21 @@ impl SilentOnIgnoredFilesEmitter { } } +impl Translate for SilentOnIgnoredFilesEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + self.emitter.fluent_bundle() + } + + fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { + self.emitter.fallback_fluent_bundle() + } +} + impl Emitter for SilentOnIgnoredFilesEmitter { fn source_map(&self) -> Option<&Lrc> { None } + fn emit_diagnostic(&mut self, db: &Diagnostic) { if db.level() == DiagnosticLevel::Fatal { return self.handle_non_ignoreable_error(db); @@ -88,14 +105,6 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } self.handle_non_ignoreable_error(db); } - - fn fluent_bundle(&self) -> Option<&Lrc> { - self.emitter.fluent_bundle() - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - self.emitter.fallback_fluent_bundle() - } } fn default_handler( @@ -340,19 +349,24 @@ mod tests { num_emitted_errors: Lrc, } + impl Translate for TestEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + None + } + + fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { + panic!("test emitter attempted to translate a diagnostic"); + } + } + impl Emitter for TestEmitter { fn source_map(&self) -> Option<&Lrc> { None } + fn emit_diagnostic(&mut self, _db: &Diagnostic) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } - fn fluent_bundle(&self) -> Option<&Lrc> { - None - } - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - panic!("test emitter attempted to translate a diagnostic"); - } } fn build_diagnostic(level: DiagnosticLevel, span: Option) -> Diagnostic { diff --git a/triagebot.toml b/triagebot.toml index ea654192bbf78..b7532e016b68e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -178,6 +178,13 @@ trigger_files = [ "src/tools/bump-stage0", ] +[autolabel."A-translation"] +trigger_files = [ + "compiler/rustc_error_messages", + "compiler/rustc_errors/src/translation.rs", + "compiler/rustc_macros/src/diagnostics" +] + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" @@ -342,3 +349,15 @@ cc = ["@rust-lang/rustfmt"] [mentions."compiler/rustc_middle/src/mir/syntax.rs"] message = "This PR changes MIR" cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"] + +[mentions."compiler/rustc_error_messages"] +message = "`rustc_error_messages` was changed" +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"] + +[mentions."compiler/rustc_errors/src/translation.rs"] +message = "`rustc_errors::translation` was changed" +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"] + +[mentions."compiler/rustc_macros/src/diagnostics"] +message = "`rustc_macros::diagnostics` was changed" +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]