diff options
Diffstat (limited to 'compiler')
32 files changed, 265 insertions, 227 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 495b255583c..0457b4e6ddc 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2399,10 +2399,10 @@ mod error { /// and we want only the best of those errors. /// /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the - /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the - /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once - /// all move errors have been reported, any diagnostics in this map are added to the buffer - /// to be emitted. + /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of + /// the `Place` of the previous most diagnostic. This happens instead of buffering the + /// error. Once all move errors have been reported, any diagnostics in this map are added + /// to the buffer to be emitted. /// /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary /// when errors in the map are being re-added to the error buffer so that errors with the @@ -2410,7 +2410,8 @@ mod error { buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>, - /// Diagnostics to be reported buffer. + /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder` + /// because it has a mixture of error diagnostics and non-error diagnostics. buffered: Vec<Diagnostic>, /// Set to Some if we emit an error during borrowck tainted_by_errors: Option<ErrorGuaranteed>, @@ -2434,11 +2435,11 @@ mod error { "diagnostic buffered but not emitted", )) } - t.buffer(&mut self.buffered); + self.buffered.push(t.into_diagnostic()); } pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { - t.buffer(&mut self.buffered); + self.buffered.push(t.into_diagnostic()); } pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) { @@ -2486,13 +2487,13 @@ mod error { // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - diag.buffer(&mut self.errors.buffered); + self.errors.buffered.push(diag.into_diagnostic()); } for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { if count > 10 { diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - diag.buffer(&mut self.errors.buffered); + self.errors.buffered.push(diag.into_diagnostic()); } if !self.errors.buffered.is_empty() { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 738c532964a..ae9595d7e64 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1,6 +1,6 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. -use rustc_errors::{Diagnostic, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; @@ -214,7 +214,7 @@ pub struct Checker<'mir, 'tcx> { local_has_storage_dead: Option<BitSet<Local>>, error_emitted: Option<ErrorGuaranteed>, - secondary_errors: Vec<Diagnostic>, + secondary_errors: Vec<DiagnosticBuilder<'tcx>>, } impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> { @@ -272,14 +272,17 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } // If we got through const-checking without emitting any "primary" errors, emit any - // "secondary" errors if they occurred. + // "secondary" errors if they occurred. Otherwise, cancel the "secondary" errors. let secondary_errors = mem::take(&mut self.secondary_errors); if self.error_emitted.is_none() { for error in secondary_errors { - self.tcx.dcx().emit_diagnostic(error); + error.emit(); } } else { assert!(self.tcx.dcx().has_errors().is_some()); + for error in secondary_errors { + error.cancel(); + } } } @@ -347,7 +350,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { self.error_emitted = Some(reported); } - ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors), + ops::DiagnosticImportance::Secondary => self.secondary_errors.push(err), } } diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index fc3ff835a81..0c1fcecb571 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.9" +annotate-snippets = "0.10" derive_setters = "0.1.6" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 97f2efa7874..980ac310119 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -12,8 +12,7 @@ use crate::{ CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, }; -use annotate_snippets::display_list::{DisplayList, FormatOptions}; -use annotate_snippets::snippet::*; +use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; use rustc_error_messages::FluentArgs; use rustc_span::source_map::SourceMap; @@ -190,11 +189,6 @@ impl AnnotateSnippetEmitter { annotation_type: annotation_type_for_level(*level), }), footer: vec![], - opt: FormatOptions { - color: true, - anonymized_line_numbers: self.ui_testing, - margin: None, - }, slices: annotated_files .iter() .map(|(file_name, source, line_index, annotations)| { @@ -222,7 +216,8 @@ impl AnnotateSnippetEmitter { // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. - eprintln!("{}", DisplayList::from(snippet)) + let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing); + eprintln!("{}", renderer.render(snippet)) } // FIXME(#59346): Is it ok to return None if there's no source_map? } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index a02909f29c4..bd7c58d904e 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -255,35 +255,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Stashes diagnostic for possible later improvement in a different, /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. - /// - /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, dcx)) = self.into_diagnostic() { - dcx.stash_diagnostic(span, key, diag); - } - } - - /// Converts the builder to a `Diagnostic` for later emission, - /// unless dcx has disabled such buffering. - fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() { - self.emit(); - return None; - } - - let diag = self.take_diag(); - - // Logging here is useful to help track down where in logs an error was - // actually emitted. - debug!("buffer: diag={:?}", diag); - - Some((diag, self.dcx)) + self.dcx.stash_diagnostic(span, key, self.into_diagnostic()); } - /// Buffers the diagnostic for later emission, - /// unless dcx has disabled such buffering. - pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) { - buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); + /// Converts the builder to a `Diagnostic` for later emission. + pub fn into_diagnostic(mut self) -> Diagnostic { + self.take_diag() } /// Delay emission of this diagnostic as a bug. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8fb539fc358..404c89ea01b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -981,6 +981,10 @@ impl DiagCtxt { inner.emit_stashed_diagnostics(); + if inner.treat_err_as_bug() { + return; + } + let warnings = match inner.deduplicated_warn_count { 0 => Cow::from(""), 1 => Cow::from("1 warning emitted"), @@ -991,9 +995,6 @@ impl DiagCtxt { 1 => Cow::from("aborting due to 1 previous error"), count => Cow::from(format!("aborting due to {count} previous errors")), }; - if inner.treat_err_as_bug() { - return; - } match (errors.len(), warnings.len()) { (0, 0) => return, @@ -1168,7 +1169,8 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); if loud && lint_level.is_error() { - inner.bump_err_count(); + inner.err_count += 1; + inner.panic_if_treat_err_as_bug(); } inner.emitter.emit_unused_externs(lint_level, unused_externs) @@ -1255,7 +1257,7 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> { - if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { + if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { diagnostic.level = Bug; } @@ -1353,10 +1355,11 @@ impl DiagCtxtInner { } if diagnostic.is_error() { if diagnostic.is_lint { - self.bump_lint_err_count(); + self.lint_err_count += 1; } else { - self.bump_err_count(); + self.err_count += 1; } + self.panic_if_treat_err_as_bug(); #[allow(deprecated)] { @@ -1447,16 +1450,6 @@ impl DiagCtxtInner { panic::panic_any(DelayedBugPanic); } - fn bump_lint_err_count(&mut self) { - self.lint_err_count += 1; - self.panic_if_treat_err_as_bug(); - } - - fn bump_err_count(&mut self) { - self.err_count += 1; - self.panic_if_treat_err_as_bug(); - } - fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { match ( diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index 872dd29a7a8..c5a53ae8313 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -8,7 +8,7 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.9" +annotate-snippets = "0.10" fluent-bundle = "0.15.2" fluent-syntax = "0.11" proc-macro2 = "1" diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 3b1b63455ed..520a64aaf5e 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -1,7 +1,4 @@ -use annotate_snippets::{ - display_list::DisplayList, - snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, -}; +use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use fluent_bundle::{FluentBundle, FluentError, FluentResource}; use fluent_syntax::{ ast::{ @@ -179,10 +176,9 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok range: (pos.start, pos.end - 1), }], }], - opt: Default::default(), }; - let dl = DisplayList::from(snippet); - eprintln!("{dl}\n"); + let renderer = Renderer::plain(); + eprintln!("{}\n", renderer.render(snippet)); } return failed(&crate_name); diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 1f88aaa6a4b..2ad96a24891 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -300,13 +300,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .expect("missing associated item"); if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { - tcx.dcx() + let reported = tcx + .dcx() .struct_span_err( binding.span, format!("{} `{}` is private", assoc_item.kind, binding.item_name), ) .with_span_label(binding.span, format!("private {}", assoc_item.kind)) .emit(); + self.set_tainted_by_errors(reported); } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index fc2ed104b3d..7b23b74f829 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -354,7 +354,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); err.span_label(name.span, format!("multiple `{name}` found")); self.note_ambiguous_inherent_assoc_type(&mut err, candidates, span); - err.emit() + let reported = err.emit(); + self.set_tainted_by_errors(reported); + reported } // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate. @@ -843,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - err.emit(); + self.set_tainted_by_errors(err.emit()); } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1f47564649e..2886ec21320 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -390,6 +390,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infer_args, ); + if let Err(err) = &arg_count.correct + && let Some(reported) = err.reported + { + self.set_tainted_by_errors(reported); + } + // Skip processing if type has no generic parameters. // Traits always have `Self` as a generic parameter, which means they will not return early // here and so associated type bindings will be handled regardless of whether there are any @@ -568,6 +574,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, modifier: constness.as_str(), }); + self.set_tainted_by_errors(e); arg_count.correct = Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] }); } @@ -966,7 +973,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - err.emit() + let reported = err.emit(); + self.set_tainted_by_errors(reported); + reported } // Search for a bound on a type parameter which includes the associated item @@ -1043,6 +1052,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, binding, ); + self.set_tainted_by_errors(reported); return Err(reported); }; debug!(?bound); @@ -1120,6 +1130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { )); } let reported = err.emit(); + self.set_tainted_by_errors(reported); if !where_bounds.is_empty() { return Err(reported); } @@ -1374,6 +1385,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_ident.name, ) }; + self.set_tainted_by_errors(reported); return Err(reported); } }; @@ -1616,12 +1628,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let kind = tcx.def_kind_descr(kind, item); let msg = format!("{kind} `{name}` is private"); let def_span = tcx.def_span(item); - tcx.dcx() + let reported = tcx + .dcx() .struct_span_err(span, msg) .with_code(rustc_errors::error_code!(E0624)) .with_span_label(span, format!("private {kind}")) .with_span_label(def_span, format!("{kind} defined here")) .emit(); + self.set_tainted_by_errors(reported); } tcx.check_stability(item, Some(block), span, None); } @@ -1862,7 +1876,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_label(span, format!("not allowed on {what}")); } extend(&mut err); - err.emit(); + self.set_tainted_by_errors(err.emit()); emitted = true; } @@ -2184,7 +2198,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - Ty::new_error(tcx, err.emit()) + let reported = err.emit(); + self.set_tainted_by_errors(reported); + Ty::new_error(tcx, reported) } else { ty } @@ -2586,7 +2602,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } - diag.emit(); + self.set_tainted_by_errors(diag.emit()); } // Find any late-bound regions declared in return type that do @@ -2686,7 +2702,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note("consider introducing a named lifetime parameter"); } - err.emit(); + self.set_tainted_by_errors(err.emit()); } } @@ -2725,7 +2741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // error. let r = derived_region_bounds[0]; if derived_region_bounds[1..].iter().any(|r1| r != *r1) { - tcx.dcx().emit_err(AmbiguousLifetimeBound { span }); + self.set_tainted_by_errors(tcx.dcx().emit_err(AmbiguousLifetimeBound { span })); } Some(r) } diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index ea2f5f50b5c..f77f250cd28 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -116,7 +116,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for more information on them, visit \ <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>", ); - err.emit(); + self.set_tainted_by_errors(err.emit()); } if regular_traits.is_empty() && auto_traits.is_empty() { @@ -127,6 +127,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|trait_ref| tcx.def_span(trait_ref)); let reported = tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); + self.set_tainted_by_errors(reported); return Ty::new_error(tcx, reported); } @@ -290,7 +291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if references_self { let def_id = i.bottom().0.def_id(); - struct_span_code_err!( + let reported = struct_span_code_err!( tcx.dcx(), i.bottom().1, E0038, @@ -303,6 +304,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .error_msg(), ) .emit(); + self.set_tainted_by_errors(reported); } ty::ExistentialTraitRef { def_id: trait_ref.def_id, args } @@ -389,6 +391,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { err.emit() }; + self.set_tainted_by_errors(e); ty::Region::new_error(tcx, e) }) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c9f89a0c3ef..e557f36037b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -35,6 +35,7 @@ use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; use rustc_trait_selection::traits::ObligationCtxt; +use std::cell::Cell; use std::iter; use std::ops::Bound; @@ -119,6 +120,7 @@ pub fn provide(providers: &mut Providers) { pub struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, + tainted_by_errors: Cell<Option<ErrorGuaranteed>>, } /////////////////////////////////////////////////////////////////////////// @@ -343,7 +345,7 @@ fn bad_placeholder<'tcx>( impl<'tcx> ItemCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { - ItemCtxt { tcx, item_def_id } + ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } } pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { @@ -357,6 +359,13 @@ impl<'tcx> ItemCtxt<'tcx> { pub fn node(&self) -> hir::Node<'tcx> { self.tcx.hir_node(self.hir_id()) } + + fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> { + match self.tainted_by_errors.get() { + Some(err) => Err(err), + None => Ok(()), + } + } } impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { @@ -492,8 +501,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { ty.ty_adt_def() } - fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { - // There's no obvious place to track this, so just let it go. + fn set_tainted_by_errors(&self, err: ErrorGuaranteed) { + self.tainted_by_errors.set(Some(err)); } fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3ceea3dc7ae..b936b0c0805 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -513,7 +513,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty bug!("unexpected sort of node in type_of(): {:?}", x); } }; - ty::EarlyBinder::bind(output) + if let Err(e) = icx.check_tainted_by_errors() { + ty::EarlyBinder::bind(Ty::new_error(tcx, e)) + } else { + ty::EarlyBinder::bind(output) + } } pub(super) fn type_of_opaque( diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 7edb5912dd5..b6b33299315 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -802,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, - ty::Error(_) => return None, + ty::Error(_) => return Some(ret_ty), _ => span_bug!( closure_span, "async fn coroutine return type not an inference variable: {ret_ty}" diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index c56a028321a..3430a5fb00d 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -498,14 +498,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // order when emitting them. let err = self.tcx().dcx().struct_span_err(span, format!("user args: {user_args:?}")); - err.buffer(&mut errors_buffer); + errors_buffer.push(err); } } if !errors_buffer.is_empty() { errors_buffer.sort_by_key(|diag| diag.span.primary_span()); - for diag in errors_buffer { - self.tcx().dcx().emit_diagnostic(diag); + for err in errors_buffer { + err.emit(); } } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 6c000380e71..03335996c03 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -82,7 +82,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg { Ok(..) => {} Err(err) => err.cancel(), }, - Err(errs) => drop(errs), + Err(errs) => errs.into_iter().for_each(|err| err.cancel()), } // If the user tried to use a key="value" flag, but is missing the quotes, provide @@ -129,9 +129,12 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string()) - else { - expected_error(); + let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(parser) => parser, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + expected_error(); + } }; let meta_item = match parser.parse_meta_item() { diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 9ca7ce09ba6..98b53945b91 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -76,8 +76,17 @@ fn decodable_body( ty_name, variants.len() ); + let tag = if variants.len() < u8::MAX as usize { + quote! { + ::rustc_serialize::Decoder::read_u8(__decoder) as usize + } + } else { + quote! { + ::rustc_serialize::Decoder::read_usize(__decoder) + } + }; quote! { - match ::rustc_serialize::Decoder::read_usize(__decoder) { + match #tag { #match_inner n => panic!(#message, n), } @@ -206,11 +215,20 @@ fn encodable_body( variant_idx += 1; result }); - quote! { - let disc = match *self { - #encode_inner - }; - ::rustc_serialize::Encoder::emit_usize(__encoder, disc); + if variant_idx < u8::MAX as usize { + quote! { + let disc = match *self { + #encode_inner + }; + ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8); + } + } else { + quote! { + let disc = match *self { + #encode_inner + }; + ::rustc_serialize::Encoder::emit_usize(__encoder, disc); + } } }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 43c5b3873b9..ce9043ec287 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -566,17 +566,28 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { body, &[ &check_alignment::CheckAlignment, - &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first + // Before inlining: trim down MIR with passes to reduce inlining work. + + // Has to be done before inlining, otherwise actual call will be almost always inlined. + // Also simple, so can just do first + &lower_slice_len::LowerSliceLenCalls, + // Perform inlining, which may add a lot of code. &inline::Inline, - // Substitutions during inlining may introduce switch on enums with uninhabited branches. + // Code from other crates may have storage markers, so this needs to happen after inlining. + &remove_storage_markers::RemoveStorageMarkers, + // Inlining and substitution may introduce ZST and useless drops. + &remove_zsts::RemoveZsts, + &remove_unneeded_drops::RemoveUnneededDrops, + // Type substitution may create uninhabited enums. &uninhabited_enum_branching::UninhabitedEnumBranching, &unreachable_prop::UnreachablePropagation, &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching), - &remove_storage_markers::RemoveStorageMarkers, - &remove_zsts::RemoveZsts, - &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering + // Inlining may have introduced a lot of redundant code and a large move pattern. + // Now, we need to shrink the generated MIR. + + // Has to run after `slice::len` lowering + &normalize_array_len::NormalizeArrayLen, &const_goto::ConstGoto, - &remove_unneeded_drops::RemoveUnneededDrops, &ref_prop::ReferencePropagation, &sroa::ScalarReplacementOfAggregates, &match_branches::MatchBranchSimplification, diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index e27875853df..94b553a07a7 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -20,6 +20,9 @@ monomorphize_recursion_limit = reached the recursion limit while instantiating `{$shrunk}` .note = `{$def_path_str}` defined here +monomorphize_start_not_found = using `fn main` requires the standard library + .help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` + monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 44beafa0873..92f001cc321 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -194,7 +194,7 @@ use rustc_target::abi::Size; use std::path::PathBuf; use crate::errors::{ - EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit, + self, EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit, TypeLengthLimit, }; @@ -1272,7 +1272,9 @@ impl<'v> RootCollector<'_, 'v> { return; }; - let start_def_id = self.tcx.require_lang_item(LangItem::Start, None); + let Some(start_def_id) = self.tcx.lang_items().start_fn() else { + self.tcx.dcx().emit_fatal(errors::StartNotFound); + }; let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output(); // Given that `main()` has no arguments, diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 2ca14673a58..bd89874b5cc 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -95,6 +95,11 @@ pub struct EncounteredErrorWhileInstantiating { } #[derive(Diagnostic)] +#[diag(monomorphize_start_not_found)] +#[help] +pub struct StartNotFound; + +#[derive(Diagnostic)] #[diag(monomorphize_unknown_cgu_collection_mode)] pub struct UnknownCguCollectionMode<'a> { pub mode: &'a str, diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7db9291921f..d7ecf577ed6 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey}; +use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -42,12 +42,12 @@ pub struct UnmatchedDelim { pub candidate_span: Option<Span>, } -pub(crate) fn parse_token_trees<'a>( - sess: &'a ParseSess, - mut src: &'a str, +pub(crate) fn parse_token_trees<'sess, 'src>( + sess: &'sess ParseSess, + mut src: &'src str, mut start_pos: BytePos, override_span: Option<Span>, -) -> Result<TokenStream, Vec<Diagnostic>> { +) -> Result<TokenStream, Vec<DiagnosticBuilder<'sess>>> { // Skip `#!`, if present. if let Some(shebang_len) = rustc_lexer::strip_shebang(src) { src = &src[shebang_len..]; @@ -76,13 +76,13 @@ pub(crate) fn parse_token_trees<'a>( let mut buffer = Vec::with_capacity(1); for unmatched in unmatched_delims { if let Some(err) = make_unclosed_delims_error(unmatched, sess) { - err.buffer(&mut buffer); + buffer.push(err); } } if let Err(errs) = res { // Add unclosing delimiter or diff marker errors for err in errs { - err.buffer(&mut buffer); + buffer.push(err); } } Err(buffer) @@ -90,16 +90,16 @@ pub(crate) fn parse_token_trees<'a>( } } -struct StringReader<'a> { - sess: &'a ParseSess, +struct StringReader<'sess, 'src> { + sess: &'sess ParseSess, /// Initial position, read-only. start_pos: BytePos, /// The absolute offset within the source_map of the current character. pos: BytePos, /// Source text to tokenize. - src: &'a str, + src: &'src str, /// Cursor for getting lexer tokens. - cursor: Cursor<'a>, + cursor: Cursor<'src>, override_span: Option<Span>, /// When a "unknown start of token: \u{a0}" has already been emitted earlier /// in this file, it's safe to treat further occurrences of the non-breaking @@ -107,8 +107,8 @@ struct StringReader<'a> { nbsp_is_whitespace: bool, } -impl<'a> StringReader<'a> { - pub fn dcx(&self) -> &'a DiagCtxt { +impl<'sess, 'src> StringReader<'sess, 'src> { + pub fn dcx(&self) -> &'sess DiagCtxt { &self.sess.dcx } @@ -526,7 +526,7 @@ impl<'a> StringReader<'a> { /// Slice of the source text from `start` up to but excluding `self.pos`, /// meaning the slice does not include the character `self.ch`. - fn str_from(&self, start: BytePos) -> &'a str { + fn str_from(&self, start: BytePos) -> &'src str { self.str_from_to(start, self.pos) } @@ -537,12 +537,12 @@ impl<'a> StringReader<'a> { } /// Slice of the source text spanning from `start` up to but excluding `end`. - fn str_from_to(&self, start: BytePos, end: BytePos) -> &'a str { + fn str_from_to(&self, start: BytePos, end: BytePos) -> &'src str { &self.src[self.src_index(start)..self.src_index(end)] } /// Slice of the source text spanning from `start` until the end - fn str_from_to_end(&self, start: BytePos) -> &'a str { + fn str_from_to_end(&self, start: BytePos) -> &'src str { &self.src[self.src_index(start)..] } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 64b3928689a..c9ff2d58e2c 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -8,18 +8,18 @@ use rustc_ast_pretty::pprust::token_to_string; use rustc_errors::{Applicability, PErr}; use rustc_span::symbol::kw; -pub(super) struct TokenTreesReader<'a> { - string_reader: StringReader<'a>, +pub(super) struct TokenTreesReader<'sess, 'src> { + string_reader: StringReader<'sess, 'src>, /// The "next" token, which has been obtained from the `StringReader` but /// not yet handled by the `TokenTreesReader`. token: Token, diag_info: TokenTreeDiagInfo, } -impl<'a> TokenTreesReader<'a> { +impl<'sess, 'src> TokenTreesReader<'sess, 'src> { pub(super) fn parse_all_token_trees( - string_reader: StringReader<'a>, - ) -> (TokenStream, Result<(), Vec<PErr<'a>>>, Vec<UnmatchedDelim>) { + string_reader: StringReader<'sess, 'src>, + ) -> (TokenStream, Result<(), Vec<PErr<'sess>>>, Vec<UnmatchedDelim>) { let mut tt_reader = TokenTreesReader { string_reader, token: Token::dummy(), @@ -35,7 +35,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_trees( &mut self, is_delimited: bool, - ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'a>>>) { + ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'sess>>>) { // Move past the opening delimiter. let (_, open_spacing) = self.bump(false); @@ -71,7 +71,7 @@ impl<'a> TokenTreesReader<'a> { } } - fn eof_err(&mut self) -> PErr<'a> { + fn eof_err(&mut self) -> PErr<'sess> { let msg = "this file contains an unclosed delimiter"; let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); for &(_, sp) in &self.diag_info.open_braces { @@ -99,7 +99,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree_open_delim( &mut self, open_delim: Delimiter, - ) -> Result<TokenTree, Vec<PErr<'a>>> { + ) -> Result<TokenTree, Vec<PErr<'sess>>> { // The span for beginning of the delimited section let pre_span = self.token.span; @@ -229,7 +229,11 @@ impl<'a> TokenTreesReader<'a> { (this_tok, this_spacing) } - fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec<PErr<'a>>) -> Vec<PErr<'a>> { + fn unclosed_delim_err( + &mut self, + tts: TokenStream, + mut errs: Vec<PErr<'sess>>, + ) -> Vec<PErr<'sess>> { // If there are unclosed delims, see if there are diff markers and if so, point them // out instead of complaining about the unclosed delims. let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); @@ -285,7 +289,7 @@ impl<'a> TokenTreesReader<'a> { return errs; } - fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'sess> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index dac7569e385..a136abaa28b 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -337,7 +337,7 @@ const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[ ]; pub(super) fn check_for_substitution( - reader: &StringReader<'_>, + reader: &StringReader<'_, '_>, pos: BytePos, ch: char, count: usize, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index b93f08a21e3..c00e318f227 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -19,7 +19,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrItem, Attribute, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, FatalError, Level, PResult}; +use rustc_errors::{DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -45,14 +45,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// A variant of 'panictry!' that works on a `Vec<Diagnostic>` instead of a single /// `DiagnosticBuilder`. macro_rules! panictry_buffer { - ($handler:expr, $e:expr) => {{ - use rustc_errors::FatalError; + ($e:expr) => {{ use std::result::Result::{Err, Ok}; match $e { Ok(e) => e, Err(errs) => { for e in errs { - $handler.emit_diagnostic(e); + e.emit(); } FatalError.raise() } @@ -100,36 +99,41 @@ pub fn parse_stream_from_source_str( /// Creates a new parser from a source string. pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(&sess.dcx, maybe_new_parser_from_source_str(sess, name, source)) + panictry_buffer!(maybe_new_parser_from_source_str(sess, name, source)) } /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial -/// token stream. +/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur +/// when they are dropped. pub fn maybe_new_parser_from_source_str( sess: &ParseSess, name: FileName, source: String, -) -> Result<Parser<'_>, Vec<Diagnostic>> { +) -> Result<Parser<'_>, Vec<DiagnosticBuilder<'_>>> { maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } -/// Creates a new parser, handling errors as appropriate if the file doesn't exist. -/// If a span is given, that is used on an error as the source of the problem. +/// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on +/// an error as the source of the problem. pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option<Span>) -> Parser<'a> { - source_file_to_parser(sess, file_to_source_file(sess, path, sp)) -} + let source_file = sess.source_map().load_file(path).unwrap_or_else(|e| { + let msg = format!("couldn't read {}: {}", path.display(), e); + let mut err = sess.dcx.struct_fatal(msg); + if let Some(sp) = sp { + err.span(sp); + } + err.emit(); + }); -/// Given a session and a `source_file`, returns a parser. -fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> { - panictry_buffer!(&sess.dcx, maybe_source_file_to_parser(sess, source_file)) + panictry_buffer!(maybe_source_file_to_parser(sess, source_file)) } -/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing the -/// initial token stream. +/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing +/// the initial token stream. fn maybe_source_file_to_parser( sess: &ParseSess, source_file: Lrc<SourceFile>, -) -> Result<Parser<'_>, Vec<Diagnostic>> { +) -> Result<Parser<'_>, Vec<DiagnosticBuilder<'_>>> { let end_pos = source_file.end_position(); let stream = maybe_file_to_stream(sess, source_file, None)?; let mut parser = stream_to_parser(sess, stream, None); @@ -142,52 +146,22 @@ fn maybe_source_file_to_parser( // Base abstractions -/// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's source_map and return the new source_file or -/// error when a file can't be read. -fn try_file_to_source_file( - sess: &ParseSess, - path: &Path, - spanopt: Option<Span>, -) -> Result<Lrc<SourceFile>, Diagnostic> { - sess.source_map().load_file(path).map_err(|e| { - let msg = format!("couldn't read {}: {}", path.display(), e); - let mut diag = Diagnostic::new(Level::Fatal, msg); - if let Some(sp) = spanopt { - diag.span(sp); - } - diag - }) -} - -/// Given a session and a path and an optional span (for error reporting), -/// adds the path to the session's `source_map` and returns the new `source_file`. -fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> Lrc<SourceFile> { - match try_file_to_source_file(sess, path, spanopt) { - Ok(source_file) => source_file, - Err(d) => { - sess.dcx.emit_diagnostic(d); - FatalError.raise(); - } - } -} - /// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( sess: &ParseSess, source_file: Lrc<SourceFile>, override_span: Option<Span>, ) -> TokenStream { - panictry_buffer!(&sess.dcx, maybe_file_to_stream(sess, source_file, override_span)) + panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -pub fn maybe_file_to_stream( - sess: &ParseSess, +fn maybe_file_to_stream<'sess>( + sess: &'sess ParseSess, source_file: Lrc<SourceFile>, override_span: Option<Span>, -) -> Result<TokenStream, Vec<Diagnostic>> { +) -> Result<TokenStream, Vec<DiagnosticBuilder<'sess>>> { let src = source_file.src.as_ref().unwrap_or_else(|| { sess.dcx.bug(format!( "cannot lex `source_file` without source: {}", diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index be50aad1303..d41cc724408 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -575,6 +575,11 @@ passes_outside_loop = passes_outside_loop_suggestion = consider labeling this block to be able to break within it +passes_panic_unwind_without_std = + unwinding panics are not supported without std + .note = since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem + .help = using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + passes_params_not_allowed = referencing function parameters is not allowed in naked functions .help = follow the calling convention in asm block to use parameters diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d934e959a41..cf3c7cc4ace 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -813,6 +813,12 @@ pub struct UnknownExternLangItem { pub struct MissingPanicHandler; #[derive(Diagnostic)] +#[diag(passes_panic_unwind_without_std)] +#[help] +#[note] +pub struct PanicUnwindWithoutStd; + +#[derive(Diagnostic)] #[diag(passes_missing_lang_item)] #[note] #[help] diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index db3d442676e..4eb0c6c275e 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -9,7 +9,9 @@ use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; +use crate::errors::{ + MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem, +}; /// Checks the crate for usage of weak lang items, returning a vector of all the /// language items required by this crate, but not defined yet. @@ -76,6 +78,8 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { if item == LangItem::PanicImpl { tcx.dcx().emit_err(MissingPanicHandler); + } else if item == LangItem::EhPersonality { + tcx.dcx().emit_err(PanicUnwindWithoutStd); } else { tcx.dcx().emit_err(MissingLangItem { name: item.name() }); } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 63bd3457eb9..287e317b10f 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -70,14 +70,6 @@ pub trait Encoder { } fn emit_raw_bytes(&mut self, s: &[u8]); - - fn emit_enum_variant<F>(&mut self, v_id: usize, f: F) - where - F: FnOnce(&mut Self), - { - self.emit_usize(v_id); - f(self); - } } // Note: all the methods in this trait are infallible, which may be surprising. @@ -132,10 +124,6 @@ pub trait Decoder { fn read_raw_bytes(&mut self, len: usize) -> &[u8]; - // Although there is an `emit_enum_variant` method in `Encoder`, the code - // patterns in decoding are different enough to encoding that there is no - // need for a corresponding `read_enum_variant` method here. - fn peek_byte(&self) -> u8; fn position(&self) -> usize; } @@ -372,15 +360,18 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> { fn encode(&self, s: &mut S) { match *self { - None => s.emit_enum_variant(0, |_| {}), - Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)), + None => s.emit_u8(0), + Some(ref v) => { + s.emit_u8(1); + v.encode(s); + } } } } impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> { fn decode(d: &mut D) -> Option<T> { - match d.read_usize() { + match d.read_u8() { 0 => None, 1 => Some(Decodable::decode(d)), _ => panic!("Encountered invalid discriminant while decoding `Option`."), @@ -391,15 +382,21 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> { impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> { fn encode(&self, s: &mut S) { match *self { - Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)), - Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)), + Ok(ref v) => { + s.emit_u8(0); + v.encode(s); + } + Err(ref v) => { + s.emit_u8(1); + v.encode(s); + } } } } impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> { fn decode(d: &mut D) -> Result<T1, T2> { - match d.read_usize() { + match d.read_u8() { 0 => Ok(T1::decode(d)), 1 => Err(T2::decode(d)), _ => panic!("Encountered invalid discriminant while decoding `Result`."), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 4235293823c..65702f76fda 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -203,18 +203,19 @@ impl Hash for RealFileName { impl<S: Encoder> Encodable<S> for RealFileName { fn encode(&self, encoder: &mut S) { match *self { - RealFileName::LocalPath(ref local_path) => encoder.emit_enum_variant(0, |encoder| { + RealFileName::LocalPath(ref local_path) => { + encoder.emit_u8(0); local_path.encode(encoder); - }), - - RealFileName::Remapped { ref local_path, ref virtual_name } => encoder - .emit_enum_variant(1, |encoder| { - // For privacy and build reproducibility, we must not embed host-dependant path - // in artifacts if they have been remapped by --remap-path-prefix - assert!(local_path.is_none()); - local_path.encode(encoder); - virtual_name.encode(encoder); - }), + } + + RealFileName::Remapped { ref local_path, ref virtual_name } => { + encoder.emit_u8(1); + // For privacy and build reproducibility, we must not embed host-dependant path + // in artifacts if they have been remapped by --remap-path-prefix + assert!(local_path.is_none()); + local_path.encode(encoder); + virtual_name.encode(encoder); + } } } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8e26327196a..da8706ea715 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3396,19 +3396,22 @@ impl Hash for TargetTriple { impl<S: Encoder> Encodable<S> for TargetTriple { fn encode(&self, s: &mut S) { match self { - TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)), - TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s - .emit_enum_variant(1, |s| { - s.emit_str(triple); - s.emit_str(contents) - }), + TargetTriple::TargetTriple(triple) => { + s.emit_u8(0); + s.emit_str(triple); + } + TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => { + s.emit_u8(1); + s.emit_str(triple); + s.emit_str(contents); + } } } } impl<D: Decoder> Decodable<D> for TargetTriple { fn decode(d: &mut D) -> Self { - match d.read_usize() { + match d.read_u8() { 0 => TargetTriple::TargetTriple(d.read_str().to_owned()), 1 => TargetTriple::TargetJson { path_for_rustdoc: PathBuf::new(), |
