From 7794ea5854094ffa15e933750196ef7c7e0e2f3b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Sep 2022 10:00:10 +0000 Subject: [PATCH 01/12] Prefer explict closure sig types over expected ones --- compiler/rustc_typeck/src/check/closure.rs | 60 ++++++++++++------- ...e#0}.SimplifyCfg-elaborate-drops.after.mir | 2 +- .../expect-fn-supply-fn.stderr | 12 ++-- ...er-vars-supply-ty-with-bound-region.stderr | 2 +- .../ui/type-alias-impl-trait/closure_args.rs | 16 +++++ .../ui/type-alias-impl-trait/closure_args2.rs | 23 +++++++ .../type-alias-impl-trait/issue-60371.stderr | 2 +- 7 files changed, 87 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/closure_args.rs create mode 100644 src/test/ui/type-alias-impl-trait/closure_args2.rs diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 55cbaf71e7cfd..9b943b160f393 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -30,7 +30,12 @@ struct ExpectedSig<'tcx> { } struct ClosureSignatures<'tcx> { + /// The signature users of the closure see. bound_sig: ty::PolyFnSig<'tcx>, + /// The signature within the function body. + /// This mostly differs in the sense that lifetimes are now early bound and any + /// opaque types from the signature expectation are overriden in case there are + /// explicit hidden types written by the user in the closure signature. liberated_sig: ty::FnSig<'tcx>, } @@ -444,18 +449,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Along the way, it also writes out entries for types that the user // wrote into our typeck results, which are then later used by the privacy // check. - match self.check_supplied_sig_against_expectation( + match self.merge_supplied_sig_with_expectation( hir_id, expr_def_id, decl, body, - &closure_sigs, + closure_sigs, ) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), - Err(_) => return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), + Err(_) => self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), } - - closure_sigs } fn sig_of_closure_with_mismatched_number_of_arguments( @@ -497,21 +500,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Enforce the user's types against the expectation. See /// `sig_of_closure_with_expectation` for details on the overall /// strategy. - fn check_supplied_sig_against_expectation( + #[instrument(level = "debug", skip(self, hir_id, expr_def_id, decl, body, expected_sigs))] + fn merge_supplied_sig_with_expectation( &self, hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, - expected_sigs: &ClosureSignatures<'tcx>, - ) -> InferResult<'tcx, ()> { + mut expected_sigs: ClosureSignatures<'tcx>, + ) -> InferResult<'tcx, ClosureSignatures<'tcx>> { // Get the signature S that the user gave. // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); - debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); + debug!(?supplied_sig); // FIXME(#45727): As discussed in [this comment][c1], naively // forcing equality here actually results in suboptimal error @@ -529,23 +533,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 self.commit_if_ok(|_| { let mut all_obligations = vec![]; + let inputs: Vec<_> = iter::zip( + decl.inputs, + supplied_sig.inputs().skip_binder(), // binder moved to (*) below + ) + .map(|(hir_ty, &supplied_ty)| { + // Instantiate (this part of..) S to S', i.e., with fresh variables. + self.replace_bound_vars_with_fresh_vars( + hir_ty.span, + LateBoundRegionConversionTime::FnCall, + // (*) binder moved to here + supplied_sig.inputs().rebind(supplied_ty), + ) + }) + .collect(); // The liberated version of this signature should be a subtype // of the liberated form of the expectation. for ((hir_ty, &supplied_ty), expected_ty) in iter::zip( - iter::zip( - decl.inputs, - supplied_sig.inputs().skip_binder(), // binder moved to (*) below - ), + iter::zip(decl.inputs, &inputs), expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. ) { - // Instantiate (this part of..) S to S', i.e., with fresh variables. - let supplied_ty = self.replace_bound_vars_with_fresh_vars( - hir_ty.span, - LateBoundRegionConversionTime::FnCall, - supplied_sig.inputs().rebind(supplied_ty), - ); // recreated from (*) above - // Check that E' = S'. let cause = self.misc(hir_ty.span); let InferOk { value: (), obligations } = @@ -564,7 +572,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; all_obligations.extend(obligations); - Ok(InferOk { value: (), obligations: all_obligations }) + let inputs = inputs.into_iter().map(|ty| self.resolve_vars_if_possible(ty)); + + expected_sigs.liberated_sig = self.tcx.mk_fn_sig( + inputs, + supplied_output_ty, + expected_sigs.liberated_sig.c_variadic, + hir::Unsafety::Normal, + Abi::RustCall, + ); + + Ok(InferOk { value: expected_sigs, obligations: all_obligations }) }) } diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir index 44b1a267b3434..96fc7e6493ab9 100644 --- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir @@ -14,7 +14,7 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:13: +1:15 _3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19 Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19 - _0 = _2; // scope 1 at $DIR/retag.rs:+2:9: +2:10 + _0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10 Retag(_0); // scope 1 at $DIR/retag.rs:+2:9: +2:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6 return; // scope 0 at $DIR/retag.rs:+3:6: +3:6 diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 26f47eb684dfc..284fc1c21f5f9 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -25,8 +25,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(&'r u32)` - found fn pointer `fn(&u32)` + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'r> fn(&'r u32)` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:39:50 @@ -34,8 +34,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^ one type is more general than the other | - = note: expected fn pointer `fn(&'x u32)` - found fn pointer `for<'r> fn(&'r u32)` + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&u32)` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:48:50 @@ -43,8 +43,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^ one type is more general than the other | - = note: expected fn pointer `fn(&u32)` - found fn pointer `for<'r> fn(&'r u32)` + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&u32)` error: aborting due to 5 previous errors diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr index db7586bee4953..d5432755cfed3 100644 --- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr +++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -6,7 +6,7 @@ LL | with_closure(|x: u32, y| {}); | help: consider giving this closure parameter an explicit type | -LL | with_closure(|x: u32, y: B| {}); +LL | with_closure(|x: u32, y: _| {}); | +++ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/closure_args.rs b/src/test/ui/type-alias-impl-trait/closure_args.rs new file mode 100644 index 0000000000000..c5e7af81d3dd0 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/closure_args.rs @@ -0,0 +1,16 @@ +// check-pass + +// regression test for https://github.com/rust-lang/rust/issues/100800 + +#![feature(type_alias_impl_trait)] + +trait Anything {} +impl Anything for T {} +type Input = impl Anything; +fn run ()>(f: F, i: Input) { + f(i); +} + +fn main() { + run(|x: u32| {println!("{x}");}, 0); +} diff --git a/src/test/ui/type-alias-impl-trait/closure_args2.rs b/src/test/ui/type-alias-impl-trait/closure_args2.rs new file mode 100644 index 0000000000000..82386c280a8e3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/closure_args2.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +trait Foo { + // This was reachable in https://github.com/rust-lang/rust/issues/100800 + fn foo(&self) { unreachable!() } +} +impl Foo for T {} + +struct B; +impl B { + fn foo(&self) {} +} + +type Input = impl Foo; +fn run1(f: F, i: Input) {f(i)} +fn run2(f: F, i: B) {f(i)} + +fn main() { + run1(|x: B| {x.foo()}, B); + run2(|x: B| {x.foo()}, B); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 082b0f0c30973..d0c04371bd793 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `(): Bug` is not satisfied --> $DIR/issue-60371.rs:10:40 | LL | const FUN: fn() -> Self::Item = || (); - | ^ the trait `Bug` is not implemented for `()` + | ^^ the trait `Bug` is not implemented for `()` | = help: the trait `Bug` is implemented for `&()` From 404b60bf6b2e761188db0e0e5984a4065afaf9cf Mon Sep 17 00:00:00 2001 From: onestacked Date: Wed, 14 Sep 2022 01:42:40 +0200 Subject: [PATCH 02/12] Constify impl Fn* &(mut) Fn* --- library/core/src/ops/function.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index c5a194b7d0a41..827851c62ae7b 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -250,9 +250,10 @@ pub trait FnOnce { mod impls { #[stable(feature = "rust1", since = "1.0.0")] - impl Fn for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + impl const Fn for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -260,9 +261,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + impl const FnMut for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -270,9 +272,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + impl const FnOnce for &F where - F: Fn, + F: ~const Fn, { type Output = F::Output; @@ -282,9 +285,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &mut F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + impl const FnMut for &mut F where - F: FnMut, + F: ~const FnMut, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -292,9 +296,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &mut F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + impl const FnOnce for &mut F where - F: FnMut, + F: ~const FnMut, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { From 478c471ce8aabb07e115f4caa18f4f1ca9acbc49 Mon Sep 17 00:00:00 2001 From: onestacked Date: Wed, 14 Sep 2022 15:10:02 +0200 Subject: [PATCH 03/12] Added Tracking Issue number. --- library/core/src/ops/function.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 827851c62ae7b..8fdf22cf6f2c8 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -250,7 +250,7 @@ pub trait FnOnce { mod impls { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] impl const Fn for &F where F: ~const Fn, @@ -261,7 +261,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] impl const FnMut for &F where F: ~const Fn, @@ -272,7 +272,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] impl const FnOnce for &F where F: ~const Fn, @@ -285,7 +285,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] impl const FnMut for &mut F where F: ~const FnMut, @@ -296,7 +296,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "none")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] impl const FnOnce for &mut F where F: ~const FnMut, From c5b9cb43d9607811ecb5d90a1495871f5e5f3542 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Sep 2022 11:40:43 +0100 Subject: [PATCH 04/12] errors: add `emit_note`/`create_note` Add `Noted` marker struct that implements `EmissionGuarantee` so that `emit_note` and `create_note` can be implemented for struct diagnostics. Signed-off-by: David Wood --- .../rustc_errors/src/diagnostic_builder.rs | 50 +++++++++++++++++++ compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_session/src/parse.rs | 13 ++++- compiler/rustc_session/src/session.rs | 10 ++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 7e29dc207acce..a5b84ea2f0c95 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -232,6 +232,56 @@ impl EmissionGuarantee for () { } } +/// Marker type which enables implementation of `create_note` and `emit_note` functions for +/// note-without-error struct diagnostics. +#[derive(Copy, Clone)] +pub struct Noted; + +impl<'a> DiagnosticBuilder<'a, Noted> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + pub(crate) fn new_note(handler: &'a Handler, message: impl Into) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Note, None, message); + Self::new_diagnostic_note(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for Noted { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + + Noted + } + + fn make_diagnostic_builder( + handler: &Handler, + msg: impl Into, + ) -> DiagnosticBuilder<'_, Self> { + DiagnosticBuilder::new_note(handler, msg) + } +} + impl<'a> DiagnosticBuilder<'a, !> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 888128f3f74e7..3f8a46d247cb0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -373,7 +373,7 @@ pub use diagnostic::{ AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder}; +pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder, Noted}; use std::backtrace::Backtrace; /// A handler deals with errors and other compiler output. diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 9bc7fbfbe1491..7b09272a9fea9 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, MultiSpan, StashKey, + DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, MultiSpan, Noted, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -361,6 +361,17 @@ impl ParseSess { self.create_warning(warning).emit() } + pub fn create_note<'a>( + &'a self, + note: impl SessionDiagnostic<'a, Noted>, + ) -> DiagnosticBuilder<'a, Noted> { + note.into_diagnostic(&self.span_diagnostic) + } + + pub fn emit_note<'a>(&'a self, note: impl SessionDiagnostic<'a, Noted>) -> Noted { + self.create_note(note).emit() + } + pub fn create_fatal<'a>( &'a self, fatal: impl SessionDiagnostic<'a, !>, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a001f87db00c6..36520a785d32f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -29,6 +29,7 @@ use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, FluentBundle, Handler, LazyFallbackBundle, MultiSpan, + Noted, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -542,6 +543,15 @@ impl Session { pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { self.parse_sess.emit_warning(warning) } + pub fn create_note<'a>( + &'a self, + note: impl SessionDiagnostic<'a, Noted>, + ) -> DiagnosticBuilder<'a, Noted> { + self.parse_sess.create_note(note) + } + pub fn emit_note<'a>(&'a self, note: impl SessionDiagnostic<'a, Noted>) -> Noted { + self.parse_sess.emit_note(note) + } pub fn create_fatal<'a>( &'a self, fatal: impl SessionDiagnostic<'a, !>, From 8a2f9c33e787149c45638a5bc50dee232244f6ef Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 30 Aug 2022 17:00:20 +0100 Subject: [PATCH 05/12] errors: implement `IntoDiagnosticArg` for `&T` Implement `IntoDiagnosticArg` for `&'a T` when `T` implements `IntoDiagnosticArg` and `Clone`. Makes it easier to write diagnostic structs that borrow something which implements `IntoDiagnosticArg`. Signed-off-by: David Wood --- .../rustc_borrowck/src/diagnostics/region_name.rs | 6 ++++++ compiler/rustc_borrowck/src/session_diagnostics.rs | 14 +------------- compiler/rustc_errors/src/diagnostic.rs | 6 ++++++ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 6c1eaa809c905..05b19fcfb999a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -187,6 +187,12 @@ impl Display for RegionName { } } +impl rustc_errors::IntoDiagnosticArg for RegionName { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId { self.body.source.def_id().expect_local() diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5d750c6ca8c7b..cd890c96a7f15 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -1,4 +1,4 @@ -use rustc_errors::{IntoDiagnosticArg, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -137,18 +137,6 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { }, } -impl IntoDiagnosticArg for &RegionName { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - format!("{}", self).into_diagnostic_arg() - } -} - -impl IntoDiagnosticArg for RegionName { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - format!("{}", self).into_diagnostic_arg() - } -} - #[derive(SessionSubdiagnostic)] pub(crate) enum RequireStaticErr { #[note(borrowck::used_impl_require_static)] diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a774b52c8a592..4abf97b2f949b 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -43,6 +43,12 @@ pub trait IntoDiagnosticArg { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; } +impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.clone().into_diagnostic_arg() + } +} + pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display); impl IntoDiagnosticArg for DiagnosticArgFromDisplay<'_> { From ae5174122942f2d6797e5956cf658386cd13f170 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 30 Aug 2022 17:01:54 +0100 Subject: [PATCH 06/12] session: impl `IntoDiagnosticArg` for `CrateType` Forward the `Display` implementation for `CrateType` to `IntoDiagnosticArg` so that it can be used in diagnostic structs. Signed-off-by: David Wood --- compiler/rustc_session/src/config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8bb3878fbbb47..cf250a27e2719 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -24,7 +24,7 @@ use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::{ColorConfig, HandlerFlags}; +use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg}; use std::collections::btree_map::{ Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, @@ -2637,6 +2637,12 @@ impl fmt::Display for CrateType { } } +impl IntoDiagnosticArg for CrateType { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { /// `-Zunpretty=normal` From 7d7cd17cd842824204f803fd2b4fdeeecb222ff9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 30 Aug 2022 17:02:57 +0100 Subject: [PATCH 07/12] errors: impl `IntoDiagnosticArg` for `TargetTriple` Forward the `Display` implementation for `CrateType` to `IntoDiagnosticArg` so that it can be used in diagnostic structs. Signed-off-by: David Wood --- compiler/rustc_errors/Cargo.toml | 20 ++++++++++---------- compiler/rustc_errors/src/diagnostic.rs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index c36ca11fad6f2..dd96348153959 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -7,22 +7,22 @@ edition = "2021" doctest = false [dependencies] -tracing = "0.1" +annotate-snippets = "0.9" +atty = "0.2" +rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_messages = { path = "../rustc_error_messages" } +rustc_hir = { path = "../rustc_hir" } +rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -rustc_macros = { path = "../rustc_macros" } -rustc_data_structures = { path = "../rustc_data_structures" } rustc_target = { path = "../rustc_target" } -rustc_hir = { path = "../rustc_hir" } -rustc_lint_defs = { path = "../rustc_lint_defs" } -unicode-width = "0.1.4" -atty = "0.2" -termcolor = "1.0" -annotate-snippets = "0.9" -termize = "0.1.1" serde = { version = "1.0.125", features = [ "derive" ] } serde_json = "1.0.59" +termcolor = "1.0" +termize = "0.1.1" +tracing = "0.1" +unicode-width = "0.1.4" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 4abf97b2f949b..7675f805493f8 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -100,7 +100,7 @@ into_diagnostic_arg_using_display!( MacroRulesNormalizedIdent, ParseIntError, StackProtector, - &TargetTriple, + TargetTriple, SplitDebuginfo ); From 677d4d095827615124cd2387834507b0e5305d12 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 19 Aug 2022 14:48:15 +0100 Subject: [PATCH 08/12] session: diagnostic migration lint on more fns Apply the diagnostic migration lint to more functions on `Session`. Signed-off-by: David Wood --- compiler/rustc_driver/src/lib.rs | 3 ++ .../locales/en-US/interface.ftl | 10 +++++++ .../locales/en-US/monomorphize.ftl | 6 ++++ .../locales/en-US/session.ftl | 2 ++ compiler/rustc_errors/src/lib.rs | 6 ++++ compiler/rustc_interface/Cargo.toml | 4 +-- compiler/rustc_interface/src/errors.rs | 21 +++++++++++++ compiler/rustc_interface/src/util.rs | 27 ++++++++--------- compiler/rustc_monomorphize/src/collector.rs | 13 ++++---- compiler/rustc_monomorphize/src/errors.rs | 14 +++++++++ .../src/partitioning/mod.rs | 17 ++++------- compiler/rustc_session/src/errors.rs | 6 ++++ compiler/rustc_session/src/session.rs | 30 +++++++++++++++++-- 13 files changed, 122 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index d6f51d7eee1af..7b3dda6e8b4b4 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1205,6 +1205,9 @@ static DEFAULT_HOOK: LazyLock) + Sync + Send + /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. +// FIXME(translation): need struct diagnostics implemented on `Handler` +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false); diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index bbcb8fc28cffa..c7ebb920ec84f 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -41,3 +41,13 @@ interface_rustc_error_unexpected_annotation = interface_failed_writing_file = failed to write file {$path}: {$error}" + +interface_unsupported_crate_type_for_target = + dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` + +interface_multiple_output_types_adaption = + due to multiple output types requested, the explicitly specified output file name will be adapted for each output type + +interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag + +interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl index 42c84fdd2d14b..5839a47fb6708 100644 --- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -24,3 +24,9 @@ monomorphize_large_assignments = monomorphize_requires_lang_item = requires `{$lang_item}` lang_item + +monomorphize_encountered_error_while_instantiating = + the above error was encountered while instantiating `{$formatted_item}` + +monomorphize_unknown_cgu_collection_mode = + unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 76cae3c81e451..bffd720b39d0c 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -66,3 +66,5 @@ session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has session_crate_name_empty = crate name must not be empty session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}` + +session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 3f8a46d247cb0..ddc9ff8a9f922 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -936,6 +936,7 @@ impl Handler { self.emit_diag_at_span(Diagnostic::new(Bug, msg), span); } + #[rustc_lint_diagnostics] pub fn span_note_without_error( &self, span: impl Into, @@ -944,6 +945,7 @@ impl Handler { self.emit_diag_at_span(Diagnostic::new(Note, msg), span); } + #[rustc_lint_diagnostics] pub fn span_note_diag( &self, span: Span, @@ -955,19 +957,23 @@ impl Handler { } // NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread + #[rustc_lint_diagnostics] pub fn fatal(&self, msg: impl Into) -> FatalError { self.inner.borrow_mut().fatal(msg) } + #[rustc_lint_diagnostics] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.inner.borrow_mut().err(msg) } + #[rustc_lint_diagnostics] pub fn warn(&self, msg: impl Into) { let mut db = DiagnosticBuilder::new(self, Warning(None), msg); db.emit(); } + #[rustc_lint_diagnostics] pub fn note_without_error(&self, msg: impl Into) { DiagnosticBuilder::new(self, Note, msg).emit(); } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index da4002d09ad02..39fad22635d8e 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -45,6 +45,7 @@ rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_resolve = { path = "../rustc_resolve" } +rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } @@ -54,9 +55,6 @@ libc = "0.2" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["libloaderapi"] } -[dev-dependencies] -rustc_target = { path = "../rustc_target" } - [features] llvm = ['rustc_codegen_llvm'] rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler'] diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 6a497aed4aba7..9ca4831438bfe 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,5 +1,7 @@ use rustc_macros::SessionDiagnostic; +use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_target::spec::TargetTriple; use std::io; use std::path::Path; @@ -87,3 +89,22 @@ pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } + +#[derive(SessionDiagnostic)] +#[diag(interface::unsupported_crate_type_for_target)] +pub struct UnsupportedCrateTypeForTarget<'a> { + pub crate_type: CrateType, + pub target_triple: &'a TargetTriple, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::multiple_output_types_adaption)] +pub struct MultipleOutputTypesAdaption; + +#[derive(SessionDiagnostic)] +#[diag(interface::ignoring_extra_filename)] +pub struct IgnoringExtraFilename; + +#[derive(SessionDiagnostic)] +#[diag(interface::ignoring_out_dir)] +pub struct IgnoringOutDir; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f7e70d355cf86..033a59ae8effd 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,3 +1,4 @@ +use crate::errors; use info; use libloading::Library; use rustc_ast as ast; @@ -572,16 +573,15 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec 1 { - sess.warn( - "due to multiple output types requested, the explicitly specified \ - output file name will be adapted for each output type", - ); + sess.emit_warning(errors::MultipleOutputTypesAdaption); None } else { if !sess.opts.cg.extra_filename.is_empty() { - sess.warn("ignoring -C extra-filename flag due to -o flag"); + sess.emit_warning(errors::IgnoringExtraFilename); } Some(out_file.clone()) }; if *odir != None { - sess.warn("ignoring --out-dir flag due to -o flag"); + sess.emit_warning(errors::IgnoringOutDir); } OutputFilenames::new( diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index be74a9d11e3c5..f746f8f70ff09 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -201,7 +201,10 @@ use std::iter; use std::ops::Range; use std::path::PathBuf; -use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit}; +use crate::errors::{ + EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, RequiresLangItem, + TypeLengthLimit, +}; #[derive(PartialEq)] pub enum MonoItemCollectionMode { @@ -524,10 +527,10 @@ fn collect_items_rec<'tcx>( && starting_point.node.is_user_defined() { let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string()); - tcx.sess.span_note_without_error( - starting_point.span, - &format!("the above error was encountered while instantiating `{}`", formatted_item), - ); + tcx.sess.emit_note(EncounteredErrorWhileInstantiating { + span: starting_point.span, + formatted_item, + }); } inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index d5f05e790d388..cb8675cc69186 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -83,3 +83,17 @@ pub struct SymbolAlreadyDefined { pub span: Option, pub symbol: String, } + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::encountered_error_while_instantiating)] +pub struct EncounteredErrorWhileInstantiating { + #[primary_span] + pub span: Span, + pub formatted_item: String, +} + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::unknown_cgu_collection_mode)] +pub struct UnknownCguCollectionMode<'a> { + pub mode: &'a str, +} diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 932edc6675f59..c124d5635900b 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -108,7 +108,7 @@ use rustc_span::symbol::Symbol; use crate::collector::InliningMap; use crate::collector::{self, MonoItemCollectionMode}; -use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy}; +use crate::errors::{SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -345,18 +345,13 @@ fn collect_and_partition_mono_items<'tcx>( ) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items { Some(ref s) => { - let mode_string = s.to_lowercase(); - let mode_string = mode_string.trim(); - if mode_string == "eager" { + let mode = s.to_lowercase(); + let mode = mode.trim(); + if mode == "eager" { MonoItemCollectionMode::Eager } else { - if mode_string != "lazy" { - let message = format!( - "Unknown codegen-item collection mode '{}'. \ - Falling back to 'lazy' mode.", - mode_string - ); - tcx.sess.warn(&message); + if mode != "lazy" { + tcx.sess.emit_warning(UnknownCguCollectionMode { mode }); } MonoItemCollectionMode::Lazy diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c6596ff249899..723ffa6ab9e9e 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -219,3 +219,9 @@ impl crate::SessionDiagnostic<'_> for InvalidCharacterInCrateName<'_> { diag } } + +#[derive(SessionDiagnostic)] +#[diag(session::optimization_fuel_exhausted)] +pub struct OptimisationFuelExhausted { + pub msg: String, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 36520a785d32f..79621f0be2868 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -4,8 +4,8 @@ pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath}; use crate::errors::{ CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported, - NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, - SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, + NotCircumventFeature, OptimisationFuelExhausted, ProfileSampleUseFileDoesNotExist, + ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, }; @@ -510,6 +510,8 @@ impl Session { self.diagnostic().span_err_with_code(sp, msg, code) } #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.diagnostic().err(msg) } @@ -595,11 +597,19 @@ impl Session { Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) } } + + // #[allow(rustc::untranslatable_diagnostic)] + // #[allow(rustc::diagnostic_outside_of_impl)] + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn>(&self, sp: S, msg: impl Into) { self.diagnostic().span_warn(sp, msg) } + + // #[allow(rustc::untranslatable_diagnostic)] + // #[allow(rustc::diagnostic_outside_of_impl)] + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn_with_code>( @@ -610,6 +620,10 @@ impl Session { ) { self.diagnostic().span_warn_with_code(sp, msg, code) } + + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn warn(&self, msg: impl Into) { self.diagnostic().warn(msg) } @@ -640,9 +654,15 @@ impl Session { self.diagnostic().delay_good_path_bug(msg) } + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn note_without_error(&self, msg: impl Into) { self.diagnostic().note_without_error(msg) } + #[rustc_lint_diagnostics] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_note_without_error>( &self, sp: S, @@ -650,6 +670,10 @@ impl Session { ) { self.diagnostic().span_note_without_error(sp, msg) } + + // #[allow(rustc::untranslatable_diagnostic)] + // #[allow(rustc::diagnostic_outside_of_impl)] + #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_note_without_error( @@ -879,7 +903,7 @@ impl Session { // We only call `msg` in case we can actually emit warnings. // Otherwise, this could cause a `delay_good_path_bug` to // trigger (issue #79546). - self.warn(&format!("optimization-fuel-exhausted: {}", msg())); + self.emit_warning(OptimisationFuelExhausted { msg: msg() }); } fuel.out_of_fuel = true; } else if fuel.remaining > 0 { From b058e41fcc17ff889d1c4682cd9a52d81db19b67 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 19 Aug 2022 14:47:41 +0100 Subject: [PATCH 09/12] incremental: migrate diagnostics Migrate the `rustc_incremental` crate's diagnostics to translatable diagnostic structs. Signed-off-by: David Wood --- .../locales/en-US/incremental.ftl | 106 +++++ compiler/rustc_error_messages/src/lib.rs | 13 +- .../rustc_incremental/src/assert_dep_graph.rs | 40 +- .../src/assert_module_sources.rs | 50 +-- compiler/rustc_incremental/src/errors.rs | 364 ++++++++++++++++++ compiler/rustc_incremental/src/lib.rs | 4 + .../src/persist/dirty_clean.rs | 63 ++- .../src/persist/file_format.rs | 21 +- compiler/rustc_incremental/src/persist/fs.rs | 111 +----- .../rustc_incremental/src/persist/load.rs | 54 ++- .../rustc_incremental/src/persist/save.rs | 24 +- .../src/persist/work_product.rs | 18 +- compiler/rustc_session/src/session.rs | 6 - .../incremental-session-fail/Makefile | 2 +- 14 files changed, 611 insertions(+), 265 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/incremental.ftl create mode 100644 compiler/rustc_incremental/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/incremental.ftl b/compiler/rustc_error_messages/locales/en-US/incremental.ftl new file mode 100644 index 0000000000000..ed9a22c02d181 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/incremental.ftl @@ -0,0 +1,106 @@ +incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} + +incremental_missing_depnode = missing `DepNode` variant + +incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected + +incremental_no_path = no path from `{$source}` to `{$target}` + +incremental_ok = OK + +incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified + +incremental_missing_query_depgraph = found CGU-reuse attribute but `-Zquery-dep-graph` was not specified + +incremental_malformed_cgu_name = + found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case). + +incremental_no_module_named = no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} + +incremental_field_associated_value_expected = associated value expected for `{$name}` + +incremental_no_field = no field `{$name}` + +incremental_assertion_auto = `except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\" + +incremental_undefined_clean_dirty_assertions_item = clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} + +incremental_undefined_clean_dirty_assertions = clean/dirty auto-assertions not yet defined for {$kind} + +incremental_repeated_depnode_label = dep-node label `{$label}` is repeated + +incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized + +incremental_not_dirty = `{$dep_node_str}` should be dirty but is not + +incremental_not_clean = `{$dep_node_str}` should be clean but is not + +incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not + +incremental_unknown_item = unknown item `{$name}` + +incremental_no_cfg = no cfg attribute + +incremental_associated_value_expected_for = associated value expected for `{$ident}` + +incremental_associated_value_expected = expected an associated value + +incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute + +incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err} + +incremental_create_new = failed to create {$name} at `{$path}`: {$err} + +incremental_write_new = failed to write {$name} to `{$path}`: {$err} + +incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err} + +incremental_create_incr_comp_dir = could not create incremental compilation {$tag} directory `{$path}`: {$err} + +incremental_create_lock = incremental compilation: could not create session directory lock file: {$lock_err} + .lock_unsupported = the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation + .cargo_help_1 = incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental) + .cargo_help_2 = the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir) + +incremental_delete_lock = error deleting lock file for incremental compilation session directory `{$path}`: {$err} + +incremental_hard_link_failed = + hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}` + +incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err} + +incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} + +incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err} + +incremental_invalid_gc_failed = + failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err} + +incremental_finalized_gc_failed = + failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err} + +incremental_session_gc_failed = + failed to garbage collect incremental compilation session directory `{$path}`: {$err} + +incremental_assert_not_loaded = + we asserted that the incremental cache should not be loaded, but it was loaded + +incremental_assert_loaded = + we asserted that an existing incremental cache directory should be successfully loaded, but it was not + +incremental_delete_incompatible = + failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err} + +incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err} + +incremental_decode_incr_cache = could not decode incremental cache: {$err} + +incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err} + +incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err} + +incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err} + +incremental_copy_workproduct_to_cache = error copying object file `{$from}` to incremental directory as `{$to}`: {$err} + +incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err} diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index b6e0f3faa73cb..5ab3a17d34beb 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -43,24 +43,25 @@ fluent_messages! { const_eval => "../locales/en-US/const_eval.ftl", driver => "../locales/en-US/driver.ftl", expand => "../locales/en-US/expand.ftl", - session => "../locales/en-US/session.ftl", - interface => "../locales/en-US/interface.ftl", + incremental => "../locales/en-US/incremental.ftl", infer => "../locales/en-US/infer.ftl", + interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", + metadata => "../locales/en-US/metadata.ftl", middle => "../locales/en-US/middle.ftl", + mir_dataflow => "../locales/en-US/mir_dataflow.ftl", monomorphize => "../locales/en-US/monomorphize.ftl", - metadata => "../locales/en-US/metadata.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl", privacy => "../locales/en-US/privacy.ftl", query_system => "../locales/en-US/query_system.ftl", - trait_selection => "../locales/en-US/trait_selection.ftl", save_analysis => "../locales/en-US/save_analysis.ftl", + session => "../locales/en-US/session.ftl", + symbol_mangling => "../locales/en-US/symbol_mangling.ftl", + trait_selection => "../locales/en-US/trait_selection.ftl", ty_utils => "../locales/en-US/ty_utils.ftl", typeck => "../locales/en-US/typeck.ftl", - mir_dataflow => "../locales/en-US/mir_dataflow.ftl", - symbol_mangling => "../locales/en-US/symbol_mangling.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 69e482ce854c0..95b48c38218d0 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -33,6 +33,7 @@ //! fn baz() { foo(); } //! ``` +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING}; @@ -133,12 +134,10 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); - } + Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode { + span: attr.span, + name: n, + }), } } }; @@ -149,16 +148,14 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); - } + Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode { + span: attr.span, + name: n, + }), } } None => { - self.tcx.sess.span_fatal(attr.span, "missing DepNode variant"); + self.tcx.sess.emit_fatal(errors::MissingDepNode { span: attr.span }); } }; self.then_this_would_need.push(( @@ -204,7 +201,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou // Return early here so as not to construct the query, which is not cheap. if if_this_changed.is_empty() { for &(target_span, _, _, _) in then_this_would_need { - tcx.sess.span_err(target_span, "no `#[rustc_if_this_changed]` annotation detected"); + tcx.sess.emit_err(errors::MissingIfThisChanged { span: target_span }); } return; } @@ -213,16 +210,13 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou let dependents = query.transitive_predecessors(source_dep_node); for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { if !dependents.contains(&target_dep_node) { - tcx.sess.span_err( - target_span, - &format!( - "no path from `{}` to `{}`", - tcx.def_path_str(source_def_id), - target_pass - ), - ); + tcx.sess.emit_err(errors::NoPath { + span: target_span, + source: tcx.def_path_str(source_def_id), + target: *target_pass, + }); } else { - tcx.sess.span_err(target_span, "OK"); + tcx.sess.emit_err(errors::Ok { span: target_span }); } } } diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index 89d419bc8e90f..2968a0e1203a9 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -22,6 +22,7 @@ //! allows for doing a more fine-grained check to see if pre- or post-lto data //! was re-used. +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::LOCAL_CRATE; @@ -66,10 +67,9 @@ impl<'tcx> AssertModuleSource<'tcx> { sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), other => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unknown cgu-reuse-kind `{}` specified", other), - ); + self.tcx + .sess + .emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other }); } } } else { @@ -77,10 +77,7 @@ impl<'tcx> AssertModuleSource<'tcx> { }; if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.tcx.sess.span_fatal( - attr.span, - "found CGU-reuse attribute but `-Zquery-dep-graph` was not specified", - ); + self.tcx.sess.emit_fatal(errors::MissingQueryDepGraph { span: attr.span }); } if !self.check_config(attr) { @@ -92,13 +89,11 @@ impl<'tcx> AssertModuleSource<'tcx> { let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string(); if !user_path.starts_with(&crate_name) { - let msg = format!( - "Found malformed codegen unit name `{}`. \ - Codegen units names must always start with the name of the \ - crate (`{}` in this case).", - user_path, crate_name - ); - self.tcx.sess.span_fatal(attr.span, &msg); + self.tcx.sess.emit_fatal(errors::MalformedCguName { + span: attr.span, + user_path, + crate_name, + }); } // Split of the "special suffix" if there is one. @@ -125,15 +120,12 @@ impl<'tcx> AssertModuleSource<'tcx> { let mut cgu_names: Vec<&str> = self.available_cgus.iter().map(|cgu| cgu.as_str()).collect(); cgu_names.sort(); - self.tcx.sess.span_err( - attr.span, - &format!( - "no module named `{}` (mangled: {}). Available modules: {}", - user_path, - cgu_name, - cgu_names.join(", ") - ), - ); + self.tcx.sess.emit_err(errors::NoModuleNamed { + span: attr.span, + user_path, + cgu_name, + cgu_names: cgu_names.join(", "), + }); } self.tcx.sess.cgu_reuse_tracker.set_expectation( @@ -151,15 +143,15 @@ impl<'tcx> AssertModuleSource<'tcx> { if let Some(value) = item.value_str() { return value; } else { - self.tcx.sess.span_fatal( - item.span(), - &format!("associated value expected for `{}`", name), - ); + self.tcx.sess.emit_fatal(errors::FieldAssociatedValueExpected { + span: item.span(), + name, + }); } } } - self.tcx.sess.span_fatal(attr.span, &format!("no field `{}`", name)); + self.tcx.sess.emit_fatal(errors::NoField { span: attr.span, name }); } /// Scan for a `cfg="foo"` attribute and check whether we have a diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs new file mode 100644 index 0000000000000..a15cff22f8756 --- /dev/null +++ b/compiler/rustc_incremental/src/errors.rs @@ -0,0 +1,364 @@ +use rustc_macros::SessionDiagnostic; +use rustc_span::{symbol::Ident, Span, Symbol}; +use std::path::{Path, PathBuf}; + +#[derive(SessionDiagnostic)] +#[diag(incremental::unrecognized_depnode)] +pub struct UnrecognizedDepNode { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::missing_depnode)] +pub struct MissingDepNode { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::missing_if_this_changed)] +pub struct MissingIfThisChanged { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::ok)] +pub struct Ok { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::no_path)] +pub struct NoPath { + #[primary_span] + pub span: Span, + pub target: Symbol, + pub source: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::unknown_reuse_kind)] +pub struct UnknownReuseKind { + #[primary_span] + pub span: Span, + pub kind: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::missing_query_depgraph)] +pub struct MissingQueryDepGraph { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::malformed_cgu_name)] +pub struct MalformedCguName { + #[primary_span] + pub span: Span, + pub user_path: String, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::no_module_named)] +pub struct NoModuleNamed<'a> { + #[primary_span] + pub span: Span, + pub user_path: &'a str, + pub cgu_name: Symbol, + pub cgu_names: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::field_associated_value_expected)] +pub struct FieldAssociatedValueExpected { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::no_field)] +pub struct NoField { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::assertion_auto)] +pub struct AssertionAuto<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, + pub e: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::undefined_clean_dirty_assertions_item)] +pub struct UndefinedCleanDirtyItem { + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::undefined_clean_dirty_assertions)] +pub struct UndefinedCleanDirty { + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::repeated_depnode_label)] +pub struct RepeatedDepNodeLabel<'a> { + #[primary_span] + pub span: Span, + pub label: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::unrecognized_depnode_label)] +pub struct UnrecognizedDepNodeLabel<'a> { + #[primary_span] + pub span: Span, + pub label: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::not_dirty)] +pub struct NotDirty<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::not_clean)] +pub struct NotClean<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::not_loaded)] +pub struct NotLoaded<'a> { + #[primary_span] + pub span: Span, + pub dep_node_str: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::unknown_item)] +pub struct UnknownItem { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::no_cfg)] +pub struct NoCfg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::associated_value_expected_for)] +pub struct AssociatedValueExpectedFor { + #[primary_span] + pub span: Span, + pub ident: Ident, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::associated_value_expected)] +pub struct AssociatedValueExpected { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::unchecked_clean)] +pub struct UncheckedClean { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_old)] +pub struct DeleteOld<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::create_new)] +pub struct CreateNew<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::write_new)] +pub struct WriteNew<'a> { + pub name: &'a str, + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::canonicalize_path)] +pub struct CanonicalizePath { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::create_incr_comp_dir)] +pub struct CreateIncrCompDir<'a> { + pub tag: &'a str, + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::create_lock)] +pub struct CreateLock<'a> { + pub lock_err: std::io::Error, + pub session_dir: &'a Path, + #[note(incremental::lock_unsupported)] + pub is_unsupported_lock: Option<()>, + #[help(incremental::cargo_help_1)] + #[help(incremental::cargo_help_2)] + pub is_cargo: Option<()>, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_lock)] +pub struct DeleteLock<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::hard_link_failed)] +pub struct HardLinkFailed<'a> { + pub path: &'a Path, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_partial)] +pub struct DeletePartial<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_full)] +pub struct DeleteFull<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::finalize)] +pub struct Finalize<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::invalid_gc_failed)] +pub struct InvalidGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::finalized_gc_failed)] +pub struct FinalizedGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::session_gc_failed)] +pub struct SessionGcFailed<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::assert_not_loaded)] +pub struct AssertNotLoaded; + +#[derive(SessionDiagnostic)] +#[diag(incremental::assert_loaded)] +pub struct AssertLoaded; + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_incompatible)] +pub struct DeleteIncompatible { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::load_dep_graph)] +pub struct LoadDepGraph { + pub path: PathBuf, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::decode_incr_cache)] +pub struct DecodeIncrCache { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::write_dep_graph)] +pub struct WriteDepGraph<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::move_dep_graph)] +pub struct MoveDepGraph<'a> { + pub from: &'a Path, + pub to: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::create_dep_graph)] +pub struct CreateDepGraph<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::copy_workproduct_to_cache)] +pub struct CopyWorkProductToCache<'a> { + pub from: &'a Path, + pub to: &'a Path, + pub err: std::io::Error, +} + +#[derive(SessionDiagnostic)] +#[diag(incremental::delete_workproduct)] +pub struct DeleteWorkProduct<'a> { + pub path: &'a Path, + pub err: std::io::Error, +} diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 1e88e8091c373..dc4a80519247b 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -3,8 +3,11 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(let_else)] +#![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -13,6 +16,7 @@ extern crate tracing; mod assert_dep_graph; pub mod assert_module_sources; +mod errors; mod persist; use assert_dep_graph::assert_dep_graph; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 710c4a01b244f..4c815d69ff395 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -19,6 +19,7 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. +use crate::errors; use rustc_ast::{self as ast, Attribute, NestedMetaItem}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::LocalDefId; @@ -198,11 +199,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let loaded_from_disk = self.loaded_from_disk(attr); for e in except.iter() { if !auto.remove(e) { - let msg = format!( - "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"", - name, e - ); - self.tcx.sess.span_fatal(attr.span, &msg); + self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e }); } } Assertion { clean: auto, dirty: except, loaded_from_disk } @@ -284,14 +281,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { // An implementation, eg `impl Trait for Foo { .. }` HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL), - _ => self.tcx.sess.span_fatal( - attr.span, - &format!( - "clean/dirty auto-assertions not yet defined \ - for Node::Item.node={:?}", - item.kind - ), - ), + _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirtyItem { + span: attr.span, + kind: format!("{:?}", item.kind), + }), } } HirNode::TraitItem(item) => match item.kind { @@ -304,10 +297,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), }, - _ => self.tcx.sess.span_fatal( - attr.span, - &format!("clean/dirty auto-assertions not yet defined for {:?}", node), - ), + _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirty { + span: attr.span, + kind: format!("{:?}", node), + }), }; let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); @@ -320,16 +313,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let label = label.trim(); if DepNode::has_label_string(label) { if out.contains(label) { - self.tcx.sess.span_fatal( - item.span(), - &format!("dep-node label `{}` is repeated", label), - ); + self.tcx + .sess + .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label }); } out.insert(label.to_string()); } else { self.tcx .sess - .span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label)); + .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label }); } } out @@ -350,7 +342,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess - .span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str)); + .emit_err(errors::NotDirty { span: item_span, dep_node_str: &dep_node_str }); } } @@ -361,7 +353,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess - .span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str)); + .emit_err(errors::NotClean { span: item_span, dep_node_str: &dep_node_str }); } } @@ -370,10 +362,9 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) { let dep_node_str = self.dep_node_str(&dep_node); - self.tcx.sess.span_err( - item_span, - &format!("`{}` should have been loaded from disk but it was not", dep_node_str), - ); + self.tcx + .sess + .emit_err(errors::NotLoaded { span: item_span, dep_node_str: &dep_node_str }); } } @@ -414,12 +405,12 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { - tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty())); + tcx.sess.emit_err(errors::UnknownItem { span: attr.span, name: item.name_or_empty() }); } } match cfg { - None => tcx.sess.span_fatal(attr.span, "no cfg attribute"), + None => tcx.sess.emit_fatal(errors::NoCfg { span: attr.span }), Some(c) => c, } } @@ -428,13 +419,11 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { if let Some(value) = item.value_str() { value } else { - let msg = if let Some(ident) = item.ident() { - format!("associated value expected for `{}`", ident) + if let Some(ident) = item.ident() { + tcx.sess.emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); } else { - "expected an associated value".to_string() - }; - - tcx.sess.span_fatal(item.span(), &msg); + tcx.sess.emit_fatal(errors::AssociatedValueExpected { span: item.span() }); + } } } @@ -458,7 +447,7 @@ impl<'tcx> FindAllAttrs<'tcx> { fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { for attr in &self.found_attrs { if !checked_attrs.contains(&attr.id) { - self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute"); + self.tcx.sess.emit_err(errors::UncheckedClean { span: attr.span }); checked_attrs.insert(attr.id); } } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 2dbd4b6bce85a..dc981c6179eeb 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -9,15 +9,15 @@ //! compiler versions don't change frequently for the typical user, being //! conservative here practically has no downside. -use std::env; -use std::fs; -use std::io::{self, Read}; -use std::path::{Path, PathBuf}; - +use crate::errors; use rustc_data_structures::memmap::Mmap; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encoder; use rustc_session::Session; +use std::env; +use std::fs; +use std::io::{self, Read}; +use std::path::{Path, PathBuf}; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; @@ -60,12 +60,7 @@ where } Err(err) if err.kind() == io::ErrorKind::NotFound => (), Err(err) => { - sess.err(&format!( - "unable to delete old {} at `{}`: {}", - name, - path_buf.display(), - err - )); + sess.emit_err(errors::DeleteOld { name, path: path_buf, err }); return; } } @@ -73,7 +68,7 @@ where let mut encoder = match FileEncoder::new(&path_buf) { Ok(encoder) => encoder, Err(err) => { - sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err)); + sess.emit_err(errors::CreateNew { name, path: path_buf, err }); return; } }; @@ -90,7 +85,7 @@ where debug!("save: data written to disk successfully"); } Err(err) => { - sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err)); + sess.emit_err(errors::WriteNew { name, path: path_buf, err }); } } } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 25c1b2e1c4387..b7fe3263adc9f 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -103,6 +103,7 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. +use crate::errors; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; @@ -225,12 +226,7 @@ pub fn prepare_session_directory( let crate_dir = match crate_dir.canonicalize() { Ok(v) => v, Err(err) => { - let reported = sess.err(&format!( - "incremental compilation: error canonicalizing path `{}`: {}", - crate_dir.display(), - err - )); - return Err(reported); + return Err(sess.emit_err(errors::CanonicalizePath { path: crate_dir, err })); } }; @@ -273,14 +269,7 @@ pub fn prepare_session_directory( debug!("successfully copied data from: {}", source_directory.display()); if !allows_links { - sess.warn(&format!( - "Hard linking files in the incremental \ - compilation cache failed. Copying files \ - instead. Consider moving the cache \ - directory to a file system which supports \ - hard linking in session dir `{}`", - session_dir.display() - )); + sess.emit_warning(errors::HardLinkFailed { path: &session_dir }); } sess.init_incr_comp_session(session_dir, directory_lock, true); @@ -295,12 +284,7 @@ pub fn prepare_session_directory( // Try to remove the session directory we just allocated. We don't // know if there's any garbage in it from the failed copy action. if let Err(err) = safe_remove_dir_all(&session_dir) { - sess.warn(&format!( - "Failed to delete partly initialized \ - session dir `{}`: {}", - session_dir.display(), - err - )); + sess.emit_warning(errors::DeletePartial { path: &session_dir, err }); } delete_session_dir_lock_file(sess, &lock_file_path); @@ -332,12 +316,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { ); if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) { - sess.warn(&format!( - "Error deleting incremental compilation \ - session directory `{}`: {}", - incr_comp_session_dir.display(), - err - )); + sess.emit_warning(errors::DeleteFull { path: &incr_comp_session_dir, err }); } let lock_file_path = lock_file_path(&*incr_comp_session_dir); @@ -380,12 +359,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { } Err(e) => { // Warn about the error. However, no need to abort compilation now. - sess.warn(&format!( - "Error finalizing incremental compilation \ - session directory `{}`: {}", - incr_comp_session_dir.display(), - e - )); + sess.emit_warning(errors::Finalize { path: &incr_comp_session_dir, err: e }); debug!("finalize_session_directory() - error, marking as invalid"); // Drop the file lock, so we can garage collect @@ -488,16 +462,7 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua debug!("{} directory created successfully", dir_tag); Ok(()) } - Err(err) => { - let reported = sess.err(&format!( - "Could not create incremental compilation {} \ - directory `{}`: {}", - dir_tag, - path.display(), - err - )); - Err(reported) - } + Err(err) => Err(sess.emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })), } } @@ -518,46 +483,20 @@ fn lock_directory( // the lock should be exclusive Ok(lock) => Ok((lock, lock_file_path)), Err(lock_err) => { - let mut err = sess.struct_err(&format!( - "incremental compilation: could not create \ - session directory lock file: {}", - lock_err - )); - if flock::Lock::error_unsupported(&lock_err) { - err.note(&format!( - "the filesystem for the incremental path at {} \ - does not appear to support locking, consider changing the \ - incremental path to a filesystem that supports locking \ - or disable incremental compilation", - session_dir.display() - )); - if std::env::var_os("CARGO").is_some() { - err.help( - "incremental compilation can be disabled by setting the \ - environment variable CARGO_INCREMENTAL=0 (see \ - https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)", - ); - err.help( - "the entire build directory can be changed to a different \ - filesystem by setting the environment variable CARGO_TARGET_DIR \ - to a different path (see \ - https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)", - ); - } - } - Err(err.emit()) + let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(()); + Err(sess.emit_err(errors::CreateLock { + lock_err, + session_dir, + is_unsupported_lock, + is_cargo: std::env::var_os("CARGO").map(|_| ()), + })) } } } fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) { if let Err(err) = safe_remove_file(&lock_file_path) { - sess.warn(&format!( - "Error deleting lock file for incremental \ - compilation session directory `{}`: {}", - lock_file_path.display(), - err - )); + sess.emit_warning(errors::DeleteLock { path: lock_file_path, err }); } } @@ -774,12 +713,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { if !lock_file_to_session_dir.values().any(|dir| *dir == directory_name) { let path = crate_directory.join(directory_name); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect invalid incremental \ - compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::InvalidGcFailed { path: &path, err }); } } } @@ -885,12 +819,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect finalized incremental \ - compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::FinalizedGcFailed { path: &path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(&path)); } @@ -907,11 +836,7 @@ fn delete_old(sess: &Session, path: &Path) { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = safe_remove_dir_all(&path) { - sess.warn(&format!( - "Failed to garbage collect incremental compilation session directory `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::SessionGcFailed { path: &path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(&path)); } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 1c5fd91690230..d5097065dda2e 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -1,5 +1,6 @@ //! Code to save/load the dep-graph from files. +use crate::errors; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; @@ -8,7 +9,7 @@ use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; use rustc_session::Session; -use std::path::Path; +use std::path::{Path, PathBuf}; use super::data::*; use super::file_format; @@ -27,11 +28,10 @@ pub enum LoadResult { }, /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - /// An error occurred. - Error { - #[allow(missing_docs)] - message: String, - }, + /// Loading the dep graph failed. + LoadDepGraph(PathBuf, std::io::Error), + /// Decoding loaded incremental cache failed. + DecodeIncrCache(Box), } impl LoadResult { @@ -40,36 +40,31 @@ impl LoadResult { // Check for errors when using `-Zassert-incremental-state` match (sess.opts.assert_incr_state, &self) { (Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => { - sess.fatal( - "We asserted that the incremental cache should not be loaded, \ - but it was loaded.", - ); + sess.emit_fatal(errors::AssertNotLoaded); } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::Error { .. } | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) + | LoadResult::DecodeIncrCache(..) + | LoadResult::DataOutOfDate, ) => { - sess.fatal( - "We asserted that an existing incremental cache directory should \ - be successfully loaded, but it was not.", - ); + sess.emit_fatal(errors::AssertLoaded); } _ => {} }; match self { - LoadResult::Error { message } => { - sess.warn(&message); + LoadResult::LoadDepGraph(path, err) => { + sess.emit_warning(errors::LoadDepGraph { path, err }); + Default::default() + } + LoadResult::DecodeIncrCache(err) => { + sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") }); Default::default() } LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { - sess.err(&format!( - "Failed to delete invalidated or incompatible \ - incremental compilation session directory contents `{}`: {}.", - dep_graph_path(sess).display(), - err - )); + sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err }); } Default::default() } @@ -90,9 +85,7 @@ fn load_data( // compiler version. Neither is an error. LoadResult::DataOutOfDate } - Err(err) => LoadResult::Error { - message: format!("could not load dep-graph from `{}`: {}", path.display(), err), - }, + Err(err) => LoadResult::LoadDepGraph(path.to_path_buf(), err), } } @@ -114,9 +107,9 @@ impl MaybeAsync> { pub fn open(self) -> LoadResult { match self { MaybeAsync::Sync(result) => result, - MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error { - message: format!("could not decode incremental cache: {:?}", e), - }), + MaybeAsync::Async(handle) => { + handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e)) + } } } } @@ -185,7 +178,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { match load_data(report_incremental_info, &path, nightly_build) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, - LoadResult::Error { message } => LoadResult::Error { message }, + LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), + LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), LoadResult::Ok { data: (bytes, start_pos) } => { let mut decoder = MemDecoder::new(&bytes, start_pos); let prev_commandline_args_hash = u64::decode(&mut decoder); diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 710350314975c..7731351a80b7c 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; @@ -59,19 +60,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { move || { sess.time("incr_comp_persist_dep_graph", || { if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) { - sess.err(&format!( - "failed to write dependency graph to `{}`: {}", - staging_dep_graph_path.display(), - err - )); + sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err }); } if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { - sess.err(&format!( - "failed to move dependency graph from `{}` to `{}`: {}", - staging_dep_graph_path.display(), - dep_graph_path.display(), - err - )); + sess.emit_err(errors::MoveDepGraph { + from: &staging_dep_graph_path, + to: &dep_graph_path, + err, + }); } }); }, @@ -163,11 +159,7 @@ pub fn build_dep_graph( let mut encoder = match FileEncoder::new(&path_buf) { Ok(encoder) => encoder, Err(err) => { - sess.err(&format!( - "failed to create dependency graph at `{}`: {}", - path_buf.display(), - err - )); + sess.emit_err(errors::CreateDepGraph { path: &path_buf, err }); return None; } }; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 2f1853c441eee..dc98fbeb0d166 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -2,6 +2,7 @@ //! //! [work products]: WorkProduct +use crate::errors; use crate::persist::fs::*; use rustc_data_structures::fx::FxHashMap; use rustc_fs_util::link_or_copy; @@ -28,12 +29,11 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let _ = saved_files.insert(ext.to_string(), file_name); } Err(err) => { - sess.warn(&format!( - "error copying object file `{}` to incremental directory as `{}`: {}", - path.display(), - path_in_incr_dir.display(), - err - )); + sess.emit_warning(errors::CopyWorkProductToCache { + from: &path, + to: &path_in_incr_dir, + err, + }); } } } @@ -49,11 +49,7 @@ pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { for (_, path) in &work_product.saved_files { let path = in_incr_comp_dir_sess(sess, path); if let Err(err) = std_fs::remove_file(&path) { - sess.warn(&format!( - "file-system error deleting outdated file `{}`: {}", - path.display(), - err - )); + sess.emit_warning(errors::DeleteWorkProduct { path: &path, err }); } } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 79621f0be2868..78b5f08a2cbc3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -598,8 +598,6 @@ impl Session { } } - // #[allow(rustc::untranslatable_diagnostic)] - // #[allow(rustc::diagnostic_outside_of_impl)] #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] @@ -607,8 +605,6 @@ impl Session { self.diagnostic().span_warn(sp, msg) } - // #[allow(rustc::untranslatable_diagnostic)] - // #[allow(rustc::diagnostic_outside_of_impl)] #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] @@ -671,8 +667,6 @@ impl Session { self.diagnostic().span_note_without_error(sp, msg) } - // #[allow(rustc::untranslatable_diagnostic)] - // #[allow(rustc::diagnostic_outside_of_impl)] #[rustc_lint_diagnostics] #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/src/test/run-make/incremental-session-fail/Makefile b/src/test/run-make/incremental-session-fail/Makefile index 0461bb926e76e..6ce1370927bc1 100644 --- a/src/test/run-make/incremental-session-fail/Makefile +++ b/src/test/run-make/incremental-session-fail/Makefile @@ -9,6 +9,6 @@ all: touch $(SESSION_DIR) # Check exit code is 1 for an error, and not 101 for ICE. $(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ] - $(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE) + $(CGREP) "could not create incremental compilation crate directory" < $(OUTPUT_FILE) # -v tests are fragile, hopefully this text won't change $(CGREP) -v "internal compiler error" < $(OUTPUT_FILE) From d7b9221405c7f852663a7c5bef660582cb5cd972 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 12 Sep 2022 10:57:34 +0300 Subject: [PATCH 10/12] change AccessLevels representation --- .../locales/en-US/privacy.ftl | 2 +- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_middle/src/middle/privacy.rs | 93 ++++++++++- compiler/rustc_passes/src/dead.rs | 11 +- compiler/rustc_passes/src/reachable.rs | 10 +- compiler/rustc_privacy/src/errors.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 37 ++++- compiler/rustc_resolve/src/access_levels.rs | 12 +- compiler/rustc_span/src/symbol.rs | 2 +- src/librustdoc/core.rs | 5 +- src/librustdoc/visit_ast.rs | 2 +- src/librustdoc/visit_lib.rs | 4 +- src/test/ui/privacy/access_levels.rs | 69 ++++---- src/test/ui/privacy/access_levels.stderr | 151 ++++++++---------- 14 files changed, 249 insertions(+), 155 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl index da987152ff660..a26d1b2b381e8 100644 --- a/compiler/rustc_error_messages/locales/en-US/privacy.ftl +++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl @@ -11,7 +11,7 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac .label = can't leak {$vis_descr} {$kind} .visibility_label = `{$descr}` declared as {$vis_descr} -privacy_report_access_level = {$descr} +privacy_report_effective_visibility = {$descr} privacy_from_private_dep_in_public_interface = {$kind} `{$descr}` from private dependency '{$krate}' in public interface diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8d88a90e39564..2512fbbd1b878 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -756,7 +756,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Testing: // ========================================================================== - rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 751c7f4648225..c595fbec0dd5c 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -1,7 +1,7 @@ //! A pass that checks to make sure private fields and methods aren't used //! outside their scopes. This pass will also generate a set of exported items //! which are available for use externally when compiled as a library. - +use crate::ty::Visibility; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; @@ -27,26 +27,107 @@ pub enum AccessLevel { Public, } +#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Default)] +pub struct EffectiveVisibility { + public: Option, + exported: Option, + reachable: Option, + reachable_from_impl_trait: Option, +} + +impl EffectiveVisibility { + pub fn get(&self, tag: AccessLevel) -> Option<&Visibility> { + match tag { + AccessLevel::Public => &self.public, + AccessLevel::Exported => &self.exported, + AccessLevel::Reachable => &self.reachable, + AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait, + } + .as_ref() + } + + fn get_mut(&mut self, tag: AccessLevel) -> &mut Option { + match tag { + AccessLevel::Public => &mut self.public, + AccessLevel::Exported => &mut self.exported, + AccessLevel::Reachable => &mut self.reachable, + AccessLevel::ReachableFromImplTrait => &mut self.reachable_from_impl_trait, + } + } + + pub fn is_public_at_level(&self, tag: AccessLevel) -> bool { + self.get(tag).map_or(false, |vis| vis.is_public()) + } +} + /// Holds a map of accessibility levels for reachable HIR nodes. #[derive(Debug, Clone)] pub struct AccessLevels { - pub map: FxHashMap, + map: FxHashMap, } -impl AccessLevels { +impl AccessLevels { + pub fn is_public_at_level(&self, id: Id, tag: AccessLevel) -> bool { + self.get_effective_vis(id) + .map_or(false, |effective_vis| effective_vis.is_public_at_level(tag)) + } + /// See `AccessLevel::Reachable`. pub fn is_reachable(&self, id: Id) -> bool { - self.map.get(&id) >= Some(&AccessLevel::Reachable) + self.is_public_at_level(id, AccessLevel::Reachable) } /// See `AccessLevel::Exported`. pub fn is_exported(&self, id: Id) -> bool { - self.map.get(&id) >= Some(&AccessLevel::Exported) + self.is_public_at_level(id, AccessLevel::Exported) } /// See `AccessLevel::Public`. pub fn is_public(&self, id: Id) -> bool { - self.map.get(&id) >= Some(&AccessLevel::Public) + self.is_public_at_level(id, AccessLevel::Public) + } + + pub fn get_access_level(&self, id: Id) -> Option { + self.get_effective_vis(id).and_then(|effective_vis| { + for level in [ + AccessLevel::Public, + AccessLevel::Exported, + AccessLevel::Reachable, + AccessLevel::ReachableFromImplTrait, + ] { + if effective_vis.is_public_at_level(level) { + return Some(level); + } + } + None + }) + } + + pub fn set_access_level(&mut self, id: Id, tag: AccessLevel) { + let mut effective_vis = self.get_effective_vis(id).copied().unwrap_or_default(); + for level in [ + AccessLevel::Public, + AccessLevel::Exported, + AccessLevel::Reachable, + AccessLevel::ReachableFromImplTrait, + ] { + if level <= tag { + *effective_vis.get_mut(level) = Some(Visibility::Public); + } + } + self.map.insert(id, effective_vis); + } + + pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + self.map.get(&id) + } + + pub fn iter(&self) -> impl Iterator { + self.map.iter() + } + + pub fn map_id(&self, f: impl Fn(Id) -> OutId) -> AccessLevels { + AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index f141d7beeb921..57f7c379d0490 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::middle::privacy; +use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; @@ -619,13 +619,10 @@ fn create_and_seed_worklist<'tcx>( // see `MarkSymbolVisitor::struct_constructors` let mut struct_constructors = Default::default(); let mut worklist = access_levels - .map .iter() - .filter_map( - |(&id, &level)| { - if level >= privacy::AccessLevel::Reachable { Some(id) } else { None } - }, - ) + .filter_map(|(&id, effective_vis)| { + effective_vis.is_public_at_level(AccessLevel::Reachable).then_some(id) + }) // Seed entry point .chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local())) .collect::>(); diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f7e3fac6b2e20..75244124e20ef 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; -use rustc_middle::middle::privacy; +use rustc_middle::middle::privacy::{self, AccessLevel}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::config::CrateType; @@ -373,7 +373,13 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { // If other crates link to us, they're going to expect to be able to // use the lang items, so we need to be sure to mark them as // exported. - reachable_context.worklist.extend(access_levels.map.keys()); + reachable_context.worklist = access_levels + .iter() + .filter_map(|(&id, effective_vis)| { + effective_vis.is_public_at_level(AccessLevel::ReachableFromImplTrait).then_some(id) + }) + .collect::>(); + for item in tcx.lang_items().items().iter() { if let Some(def_id) = *item { if let Some(def_id) = def_id.as_local() { diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 63f83f8965ec5..705ad567aa779 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -76,8 +76,8 @@ pub struct InPublicInterface<'a> { } #[derive(SessionDiagnostic)] -#[diag(privacy::report_access_level)] -pub struct ReportAccessLevel { +#[diag(privacy::report_effective_visibility)] +pub struct ReportEffectiveVisibility { #[primary_span] pub span: Span, pub descr: String, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index afd423dc5fa1a..9a1603fb835ee 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -43,7 +43,7 @@ use std::{cmp, fmt, mem}; use errors::{ FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface, - InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel, + InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportEffectiveVisibility, UnnamedItemIsPrivate, }; @@ -377,7 +377,7 @@ impl VisibilityLike for Option { // (which require reaching the `DefId`s in them). const SHALLOW: bool = true; fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self { - cmp::min(find.access_levels.map.get(&def_id).copied(), find.min) + cmp::min(find.access_levels.get_access_level(def_id), find.min) } } @@ -417,7 +417,7 @@ struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> { impl<'tcx> EmbargoVisitor<'tcx> { fn get(&self, def_id: LocalDefId) -> Option { - self.access_levels.map.get(&def_id).copied() + self.access_levels.get_access_level(def_id) } fn update_with_hir_id( @@ -434,7 +434,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { let old_level = self.get(def_id); // Accessibility levels can only grow. if level > old_level { - self.access_levels.map.insert(def_id, level.unwrap()); + self.access_levels.set_access_level(def_id, level.unwrap()); self.changed = true; level } else { @@ -915,10 +915,31 @@ pub struct TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { fn access_level_diagnostic(&mut self, def_id: LocalDefId) { - if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) { - let access_level = format!("{:?}", self.access_levels.map.get(&def_id)); - let span = self.tcx.def_span(def_id.to_def_id()); - self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level }); + let span = self.tcx.def_span(def_id.to_def_id()); + if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { + let mut error_msg = String::new(); + + let effective_vis = + self.access_levels.get_effective_vis(def_id).copied().unwrap_or_default(); + for level in [ + AccessLevel::Public, + AccessLevel::Exported, + AccessLevel::Reachable, + AccessLevel::ReachableFromImplTrait, + ] { + let vis_str = match effective_vis.get(level) { + Some(ty::Visibility::Restricted(restricted_id)) => { + format!("pub({})", self.tcx.item_name(restricted_id.to_def_id())) + } + Some(ty::Visibility::Public) => "pub".to_string(), + None => "pub(self)".to_string(), + }; + if level != AccessLevel::Public { + error_msg.push_str(", "); + } + error_msg.push_str(&format!("{:?}: {}", level, vis_str)); + } + self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); } } } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 0a3add2e0f532..9b1111c02c73f 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -46,7 +46,7 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level). fn set_bindings_access_level(&mut self, module_id: LocalDefId) { assert!(self.r.module_map.contains_key(&&module_id.to_def_id())); - let module_level = self.r.access_levels.map.get(&module_id).copied(); + let module_level = self.r.access_levels.get_access_level(module_id); if !module_level.is_some() { return; } @@ -103,9 +103,9 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { def_id: LocalDefId, access_level: Option, ) -> Option { - let old_level = self.r.access_levels.map.get(&def_id).copied(); + let old_level = self.r.access_levels.get_access_level(def_id); if old_level < access_level { - self.r.access_levels.map.insert(def_id, access_level.unwrap()); + self.r.access_levels.set_access_level(def_id, access_level.unwrap()); self.changed = true; access_level } else { @@ -131,7 +131,7 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { // Foreign modules inherit level from parents. ast::ItemKind::ForeignMod(..) => { let parent_level = - self.r.access_levels.map.get(&self.r.local_parent(def_id)).copied(); + self.r.access_levels.get_access_level(self.r.local_parent(def_id)); self.set_access_level(item.id, parent_level); } @@ -151,7 +151,7 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { self.set_bindings_access_level(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); - let variant_level = self.r.access_levels.map.get(&variant_def_id).copied(); + let variant_level = self.r.access_levels.get_access_level(variant_def_id); for field in variant.data.fields() { self.set_access_level(field.id, variant_level); } @@ -159,7 +159,7 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { } ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { - let inherited_level = self.r.access_levels.map.get(&def_id).copied(); + let inherited_level = self.r.access_levels.get_access_level(def_id); for field in def.fields() { if field.vis.kind.is_pub() { self.set_access_level(field.id, inherited_level); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5bddcd3481974..530198d8ad8cf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1211,7 +1211,6 @@ symbols! { rust_eh_unregister_frames, rust_oom, rustc, - rustc_access_level, rustc_allocator, rustc_allocator_nounwind, rustc_allocator_zeroed, @@ -1239,6 +1238,7 @@ symbols! { rustc_dump_program_clauses, rustc_dump_user_substs, rustc_dump_vtable, + rustc_effective_visibility, rustc_error, rustc_evaluate_where_clauses, rustc_expected_cgu_reuse, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c48b25aea4a37..76562d26a5502 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,7 +10,6 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, Path, TraitCandidate}; use rustc_interface::interface; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_resolve as resolve; use rustc_session::config::{self, CrateType, ErrorOutputType}; @@ -364,9 +363,7 @@ pub(crate) fn run_global_ctxt( .copied() .filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)) .collect(); - let access_levels = AccessLevels { - map: tcx.privacy_access_levels(()).map.iter().map(|(k, v)| (k.to_def_id(), *v)).collect(), - }; + let access_levels = tcx.privacy_access_levels(()).map_id(Into::into); let mut ctxt = DocContext { tcx, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c27ac0ac40e1d..e6cef4a326ac0 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } else { // All items need to be handled here in case someone wishes to link // to them with intra-doc links - self.cx.cache.access_levels.map.insert(did, AccessLevel::Public); + self.cx.cache.access_levels.set_access_level(did, AccessLevel::Public); } } } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index f01ec38665c01..8221e0998d79a 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -38,10 +38,10 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { fn update(&mut self, did: DefId, level: Option) -> Option { let is_hidden = self.tcx.is_doc_hidden(did); - let old_level = self.access_levels.map.get(&did).cloned(); + let old_level = self.access_levels.get_access_level(did); // Accessibility levels can only grow if level > old_level && !is_hidden { - self.access_levels.map.insert(did, level.unwrap()); + self.access_levels.set_access_level(did, level.unwrap()); level } else { old_level diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index d51d2b57267b6..aa718ab9254df 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -1,49 +1,62 @@ #![feature(rustc_attrs)] -#[rustc_access_level] mod outer { //~ ERROR None - #[rustc_access_level] pub mod inner { //~ ERROR Some(Exported) - #[rustc_access_level] - extern "C" { //~ ERROR Some(Exported) - #[rustc_access_level] static a: u8; //~ ERROR None - #[rustc_access_level] pub fn b(); //~ ERROR Some(Exported) - } - #[rustc_access_level] - pub trait Trait { //~ ERROR Some(Exported) - #[rustc_access_level] const A: i32; //~ ERROR Some(Exported) - #[rustc_access_level] type B; //~ ERROR Some(Exported) +#[rustc_effective_visibility] +mod outer { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + #[rustc_effective_visibility] + pub mod inner1 { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + + #[rustc_effective_visibility] + extern "C" {} //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + + #[rustc_effective_visibility] + pub trait PubTrait { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + const A: i32; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + type B; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub } - #[rustc_access_level] - pub struct Struct { //~ ERROR Some(Exported) - #[rustc_access_level] a: u8, //~ ERROR None - #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported) - } + #[rustc_effective_visibility] + struct PrivStruct; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) - #[rustc_access_level] - pub union Union { //~ ERROR Some(Exported) - #[rustc_access_level] a: u8, //~ ERROR None - #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported) + #[rustc_effective_visibility] + pub union PubUnion { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + #[rustc_effective_visibility] + pub b: u8, //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub } - #[rustc_access_level] - pub enum Enum { //~ ERROR Some(Exported) - #[rustc_access_level] A( //~ ERROR Some(Exported) - #[rustc_access_level] Struct, //~ ERROR Some(Exported) - #[rustc_access_level] Union, //~ ERROR Some(Exported) + #[rustc_effective_visibility] + pub enum Enum { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + A( //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + PubUnion, //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub ), } } - #[rustc_access_level] macro_rules! none_macro { //~ ERROR None + #[rustc_effective_visibility] + macro_rules! none_macro { //~ Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) () => {}; } #[macro_export] - #[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public) + #[rustc_effective_visibility] + macro_rules! public_macro { //~ Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub () => {}; } + + #[rustc_effective_visibility] + pub struct ReachableStruct { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + pub a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub + } } -pub use outer::inner; +pub use outer::inner1; + +pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index f326293c384a5..2ed6c330a2f97 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -1,125 +1,104 @@ -error: None - --> $DIR/access_levels.rs:3:23 +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:4:1 | -LL | #[rustc_access_level] mod outer { - | ^^^^^^^^^ +LL | mod outer { + | ^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:4:27 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:6:5 | -LL | #[rustc_access_level] pub mod inner { - | ^^^^^^^^^^^^^ +LL | pub mod inner1 { + | ^^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:6:9 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:9:9 | -LL | / extern "C" { -LL | | #[rustc_access_level] static a: u8; -LL | | #[rustc_access_level] pub fn b(); -LL | | } - | |_________^ +LL | extern "C" {} + | ^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:11:9 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:12:9 | -LL | pub trait Trait { - | ^^^^^^^^^^^^^^^ +LL | pub trait PubTrait { + | ^^^^^^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:17:9 +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:20:9 | -LL | pub struct Struct { +LL | struct PrivStruct; | ^^^^^^^^^^^^^^^^^ -error: None - --> $DIR/access_levels.rs:18:35 - | -LL | #[rustc_access_level] a: u8, - | ^^^^^ - -error: Some(Exported) - --> $DIR/access_levels.rs:19:35 - | -LL | #[rustc_access_level] pub b: u8, - | ^^^^^^^^^ - -error: Some(Exported) +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub --> $DIR/access_levels.rs:23:9 | -LL | pub union Union { - | ^^^^^^^^^^^^^^^ +LL | pub union PubUnion { + | ^^^^^^^^^^^^^^^^^^ -error: None - --> $DIR/access_levels.rs:24:35 +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:25:13 | -LL | #[rustc_access_level] a: u8, - | ^^^^^ +LL | a: u8, + | ^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:25:35 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:27:13 | -LL | #[rustc_access_level] pub b: u8, - | ^^^^^^^^^ +LL | pub b: u8, + | ^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:29:9 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:31:9 | LL | pub enum Enum { | ^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:30:35 - | -LL | #[rustc_access_level] A( - | ^ - -error: Some(Exported) - --> $DIR/access_levels.rs:31:39 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:33:13 | -LL | #[rustc_access_level] Struct, - | ^^^^^^ +LL | A( + | ^ -error: Some(Exported) - --> $DIR/access_levels.rs:32:39 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:35:17 | -LL | #[rustc_access_level] Union, - | ^^^^^ +LL | PubUnion, + | ^^^^^^^^ -error: None - --> $DIR/access_levels.rs:37:27 +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:41:5 | -LL | #[rustc_access_level] macro_rules! none_macro { - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | macro_rules! none_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^ -error: Some(Public) - --> $DIR/access_levels.rs:42:27 +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:47:5 | -LL | #[rustc_access_level] macro_rules! public_macro { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | macro_rules! public_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:12:35 +error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:52:5 | -LL | #[rustc_access_level] const A: i32; - | ^^^^^^^^^^^^ +LL | pub struct ReachableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:13:35 +error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:54:9 | -LL | #[rustc_access_level] type B; - | ^^^^^^ +LL | pub a: u8, + | ^^^^^^^^^ -error: None - --> $DIR/access_levels.rs:7:35 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:14:13 | -LL | #[rustc_access_level] static a: u8; - | ^^^^^^^^^^^^ +LL | const A: i32; + | ^^^^^^^^^^^^ -error: Some(Exported) - --> $DIR/access_levels.rs:8:35 +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:16:13 | -LL | #[rustc_access_level] pub fn b(); - | ^^^^^^^^^^ +LL | type B; + | ^^^^^^ -error: aborting due to 20 previous errors +error: aborting due to 17 previous errors From 8df181d26b5c79e7e84d68c5695e9eb4365367c9 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 13 Sep 2022 16:13:43 -0700 Subject: [PATCH 11/12] Improve handing of env vars during bootstrap process This CL modifies the handing of env vars during the bootstrap process in two ways: 1. Replaces '-' characters with '_' characters in target names to increase compatibility with different shells 2. Passes Stage0 snapshot compiler related env vars to early invocations of Cargo --- src/bootstrap/bootstrap.py | 15 +++++++++++---- src/bootstrap/builder.rs | 13 +++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index cc08ae5f99f0e..19ace2cdf5761 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -732,9 +732,19 @@ def build_bootstrap(self, color): (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" + # Export Stage0 snapshot compiler related env variables + build_section = f"target.{self.build}" + host_triple_sanitized = self.build.replace("-", "_") + var_data = { + "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib" + } + for var_name, toml_key in var_data.items(): + toml_val = self.get_toml(toml_key, build_section) + if toml_val != None: + env[f"{var_name}_{host_triple_sanitized}"] = toml_val + # preserve existing RUSTFLAGS env.setdefault("RUSTFLAGS", "") - build_section = "target.{}".format(self.build) target_features = [] if self.get_toml("crt-static", build_section) == "true": target_features += ["+crt-static"] @@ -742,9 +752,6 @@ def build_bootstrap(self, color): target_features += ["-crt-static"] if target_features: env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features)) - target_linker = self.get_toml("linker", build_section) - if target_linker is not None: - env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros" if self.get_toml("deny-warnings", "rust") != "false": diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 14e8ebd6876b4..b654db6dbe9a3 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1940,25 +1940,26 @@ impl<'a> Builder<'a> { _ => s.display().to_string(), } }; + let triple_underscored = target.triple.replace("-", "_"); let cc = ccacheify(&self.cc(target)); - cargo.env(format!("CC_{}", target.triple), &cc); + cargo.env(format!("CC_{}", triple_underscored), &cc); let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); - cargo.env(format!("CFLAGS_{}", target.triple), &cflags); + cargo.env(format!("CFLAGS_{}", triple_underscored), &cflags); if let Some(ar) = self.ar(target) { let ranlib = format!("{} s", ar.display()); cargo - .env(format!("AR_{}", target.triple), ar) - .env(format!("RANLIB_{}", target.triple), ranlib); + .env(format!("AR_{}", triple_underscored), ar) + .env(format!("RANLIB_{}", triple_underscored), ranlib); } if let Ok(cxx) = self.cxx(target) { let cxx = ccacheify(&cxx); let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); cargo - .env(format!("CXX_{}", target.triple), &cxx) - .env(format!("CXXFLAGS_{}", target.triple), cxxflags); + .env(format!("CXX_{}", triple_underscored), &cxx) + .env(format!("CXXFLAGS_{}", triple_underscored), cxxflags); } } From 4cdf264e6fe58325dcedb2f571cbac4aed095eb7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 9 Sep 2022 15:34:11 +0000 Subject: [PATCH 12/12] cache collect_trait_impl_trait_tys --- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 3 ++- compiler/rustc_query_impl/src/on_disk_cache.rs | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 9b1fedd0b533c..6bdf5a023b6c3 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -102,7 +102,7 @@ macro_rules! arena_types { [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>, - [] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, + [decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, ]); ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0fe22a26cd503..5cc2b7984d709 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -164,7 +164,8 @@ rustc_queries! { query collect_trait_impl_trait_tys(key: DefId) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { - desc { "better description please" } + desc { "compare an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } + cache_on_disk_if { key.is_local() } separate_provide_extern } diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 5ef95911f562d..0e93f3ce1d646 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -798,6 +798,12 @@ impl<'a, 'tcx> Decodable> for &'tcx FxHashSet } } +impl<'a, 'tcx> Decodable> for &'tcx FxHashMap> { + fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { + RefDecodable::decode(d) + } +} + impl<'a, 'tcx> Decodable> for &'tcx IndexVec> {