diff options
| author | bors <bors@rust-lang.org> | 2022-08-17 14:49:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-17 14:49:05 +0000 |
| commit | 9c20b2a8cc7588decb6de25ac6a7912dcef24d65 (patch) | |
| tree | 099d3858d3f4e681d153efb1761fb8951b08afa5 /compiler | |
| parent | 86c6ebee8fa0a5ad1e18e375113b06bd2849b634 (diff) | |
| parent | 1199dbdcf5f651060c1cf1ab089c3feafcd54100 (diff) | |
| download | rust-9c20b2a8cc7588decb6de25ac6a7912dcef24d65.tar.gz rust-9c20b2a8cc7588decb6de25ac6a7912dcef24d65.zip | |
Auto merge of #100677 - matthiaskrgr:rollup-au41ho1, r=matthiaskrgr
Rollup of 15 pull requests
Successful merges:
- #99474 (Rustdoc json tests: New `@hasexact` test command)
- #99972 (interpret: only consider 1-ZST when searching for receiver)
- #100018 (Clean up `LitKind`)
- #100379 (triagebot: add translation-related mention groups)
- #100389 (Do not report cycle error when inferring return type for suggestion)
- #100489 (`is_knowable` use `Result` instead of `Option`)
- #100532 (unwind: don't build dependency when building for Miri)
- #100608 (needless separation of impl blocks)
- #100621 (Pass +atomics-32 feature for {arm,thumb}v4t-none-eabi)
- #100646 (Migrate emoji identifier diagnostics to `SessionDiagnostic` in rustc_interface)
- #100652 (Remove deferred sized checks (make them eager))
- #100655 (Update books)
- #100656 (Update cargo)
- #100660 (Fixed a few documentation errors)
- #100661 (Fixed a few documentation errors)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
40 files changed, 293 insertions, 247 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3d8eee6f597..268b0527b1c 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 bc4f183d9b1..0d114f1366c 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<Symbol> { - 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 9c18f55c03b..e6351d89c6c 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<LitKind, LitError> { + pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> { 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<Lit, LitError> { - Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span }) + pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<Lit, LitError> { + 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 5f5667ce905..1ac1d689efb 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 c454034efa7..8749a13c5dd 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<Target = pp::Printer> + 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 a1afec410c1..c0f35d122f8 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 d3de10ca4a2..467ac34ded9 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 ceef893e862..5ab70e441b8 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 53c13873b10..08026c9d357 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 8bf3a0799b6..d78bbc3c932 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 dbd55590e5c..2930d09d71f 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<rustc_errors::FluentBundle>> { + 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<SourceMap>> { None } - - fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { - 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 d563e35f910..c8557d172ed 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 52952a7932d..258780ecaea 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<T: Copy> Atomic<T> { #[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 00000000000..2c05abd8c09 --- /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 9e73a399809..6ae4dab3a35 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 3df562c7eda..b32fc3c719b 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<FluentBundle>> { + 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<FluentBundle>> { - 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 753e2f07c04..6c1bfcb9919 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<SourceMap>>; - /// 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<FluentBundle>>; - - /// 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::<String>(), - ) - } - - /// 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<SourceMap>> { - self.sm.as_ref() - } - +impl Translate for EmitterWriter { fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { 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<SourceMap>> { + 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<String>, } -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc<SourceMap>> { - None - } - +impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { 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<SourceMap>> { + 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 b8cd334b4c6..1680c6accd7 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<FluentBundle>> { + 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<FluentBundle>> { - 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 395bf5aad01..6555b93ac0b 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 00000000000..65338f56d9c --- /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<FluentBundle>>; + + /// 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::<String>(), + ) + } + + /// 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 fa3e2a4a5b8..b971a63ec89 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<ast::Expr> { + fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> { 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<ast::Expr> { 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<ast::Expr> { 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<ast::Expr> { self.expr_lit(sp, ast::LitKind::Bool(value)) } + pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) + } + + pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::Char(ch)) + } + + pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes))) + } + /// `[expr1, expr2, ...]` pub fn expr_array(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { 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<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) - } - pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> { 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 fc808401a5e..99fe474541e 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 7d9a4aed0bf..beb33c05913 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 e6fcb84730e..0f754dddbec 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 1ecbc876c8d..da4002d09ad 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 8f083591786..e00d0b7d0d8 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<Span>, + #[suggestion(code = "ferris", applicability = "maybe-incorrect")] + first_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(interface::emoji_identifier)] +struct EmojiIdentifier { + #[primary_span] + spans: Vec<Span>, + 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 fe2712525ee..8f22221324a 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 cfc75f673c8..8a727d9a182 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 9d6d632c2e8..c824566c35f 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 5673bb83b15..c37ae4f3253 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 718a2971c40..0ed48f8d4a0 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::PolyFnSig<'tcx>, 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 a76ffe808c3..797dfe52bd1 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 7125d141af7..bdaaed8b5d0 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 9bb41b900b8..985600d9ebc 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<Conflict> { +) -> 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 50e9b95a445..d67bd6292b4 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 c01ac197991..46b50dd92f1 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<Conflict> { + 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 c82c819169d..5ff62f36b45 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 3a809334511..1d9d04ceec0 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 cd152eb97f1..f3115fc5c02 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<Box<dyn TraitEngine<'tcx>>>, - // Some additional `Sized` obligations badly affect type inference. - // These obligations are added in a later stage of typeck. - pub(super) deferred_sized_obligations: - RefCell<Vec<(Ty<'tcx>, 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(<dyn TraitEngine<'_>>::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 1b50209ee64..dfbef544b1d 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() { |
