diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 2049422b79a30..cef7bf1e8034d 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -573,7 +573,7 @@ pub(crate) fn run_pass_manager( module: &mut ModuleCodegen, thin: bool, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name); + let _timer = cgcx.prof.verbose_generic_activity_with_arg("LLVM_lto_optimize", &*module.name); let config = cgcx.config(module.kind); // Now we have one massive module inside of llmod. Time to run the diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 680b9b642d9b2..6188094bbbdd4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1637,7 +1637,7 @@ fn start_executing_work( llvm_start_time: &mut Option>, ) { if config.time_module && llvm_start_time.is_none() { - *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes", "crate")); + *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes")); } } } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index d8b26f9840b63..ba1960805d84b 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -158,30 +158,21 @@ pub struct SelfProfilerRef { // actually enabled. event_filter_mask: EventFilter, - // Print verbose generic activities to stdout + // Print verbose generic activities to stderr? print_verbose_generic_activities: bool, - - // Print extra verbose generic activities to stdout - print_extra_verbose_generic_activities: bool, } impl SelfProfilerRef { pub fn new( profiler: Option>, print_verbose_generic_activities: bool, - print_extra_verbose_generic_activities: bool, ) -> SelfProfilerRef { // If there is no SelfProfiler then the filter mask is set to NONE, // ensuring that nothing ever tries to actually access it. let event_filter_mask = profiler.as_ref().map_or(EventFilter::empty(), |p| p.event_filter_mask); - SelfProfilerRef { - profiler, - event_filter_mask, - print_verbose_generic_activities, - print_extra_verbose_generic_activities, - } + SelfProfilerRef { profiler, event_filter_mask, print_verbose_generic_activities } } /// This shim makes sure that calls only get executed if the filter mask @@ -214,7 +205,7 @@ impl SelfProfilerRef { /// Start profiling a verbose generic activity. Profiling continues until the /// VerboseTimingGuard returned from this call is dropped. In addition to recording /// a measureme event, "verbose" generic activities also print a timing entry to - /// stdout if the compiler is invoked with -Ztime or -Ztime-passes. + /// stderr if the compiler is invoked with -Ztime-passes. pub fn verbose_generic_activity<'a>( &'a self, event_label: &'static str, @@ -225,11 +216,8 @@ impl SelfProfilerRef { VerboseTimingGuard::start(message, self.generic_activity(event_label)) } - /// Start profiling an extra verbose generic activity. Profiling continues until the - /// VerboseTimingGuard returned from this call is dropped. In addition to recording - /// a measureme event, "extra verbose" generic activities also print a timing entry to - /// stdout if the compiler is invoked with -Ztime-passes. - pub fn extra_verbose_generic_activity<'a, A>( + /// Like `verbose_generic_activity`, but with an extra arg. + pub fn verbose_generic_activity_with_arg<'a, A>( &'a self, event_label: &'static str, event_arg: A, @@ -237,7 +225,7 @@ impl SelfProfilerRef { where A: Borrow + Into, { - let message = if self.print_extra_verbose_generic_activities { + let message = if self.print_verbose_generic_activities { Some(format!("{}({})", event_label, event_arg.borrow())) } else { None @@ -745,27 +733,9 @@ impl Drop for VerboseTimingGuard<'_> { if let Some((start_time, start_rss, ref message)) = self.start_and_message { let end_rss = get_resident_set_size(); let dur = start_time.elapsed(); - - if should_print_passes(dur, start_rss, end_rss) { - print_time_passes_entry(&message, dur, start_rss, end_rss); - } - } - } -} - -fn should_print_passes(dur: Duration, start_rss: Option, end_rss: Option) -> bool { - if dur.as_millis() > 5 { - return true; - } - - if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) { - let change_rss = end_rss.abs_diff(start_rss); - if change_rss > 0 { - return true; + print_time_passes_entry(&message, dur, start_rss, end_rss); } } - - false } pub fn print_time_passes_entry( @@ -774,6 +744,26 @@ pub fn print_time_passes_entry( start_rss: Option, end_rss: Option, ) { + // Print the pass if its duration is greater than 5 ms, or it changed the + // measured RSS. + let is_notable = || { + if dur.as_millis() > 5 { + return true; + } + + if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) { + let change_rss = end_rss.abs_diff(start_rss); + if change_rss > 0 { + return true; + } + } + + false + }; + if !is_notable() { + return; + } + let rss_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as usize; let rss_change_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as i128; diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index fcd49f5d01567..7d5604fcabcc9 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -127,10 +127,13 @@ pub struct TimePassesCallbacks { } impl Callbacks for TimePassesCallbacks { + // JUSTIFICATION: the session doesn't exist at this point. + #[allow(rustc::bad_opt_access)] fn config(&mut self, config: &mut interface::Config) { - // If a --prints=... option has been given, we don't print the "total" - // time because it will mess up the --prints output. See #64339. - self.time_passes = config.opts.prints.is_empty() && config.opts.time_passes(); + // If a --print=... option has been given, we don't print the "total" + // time because it will mess up the --print output. See #64339. + // + self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes; config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath; } } diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 0fd9b0ead167c..7e28f22c0ba8b 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -436,4 +436,5 @@ lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds .specifically = this associated type bound is unsatisfied for `{$proj_ty}` - .suggestion = add this bound + +lint_opaque_hidden_inferred_bound_sugg = add this bound diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 824144aeac004..a2636f23a4f25 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2,7 +2,7 @@ use crate::check::intrinsicck::InlineAsmCtxt; use super::coercion::CoerceMany; use super::compare_method::check_type_bounds; -use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; +use super::compare_method::{compare_impl_method, compare_ty_impl}; use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; @@ -1048,14 +1048,10 @@ fn check_impl_items_against_trait<'tcx>( let impl_item_full = tcx.hir().impl_item(impl_item.id); match impl_item_full.kind { hir::ImplItemKind::Const(..) => { - // Find associated const definition. - compare_const_impl( - tcx, - &ty_impl_item, - impl_item.span, - &ty_trait_item, - impl_trait_ref, - ); + let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( + impl_item.id.def_id.def_id, + ty_impl_item.trait_item_def_id.unwrap(), + )); } hir::ImplItemKind::Fn(..) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index ae98a8f6209de..d006948c58793 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -1,6 +1,6 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; -use hir::def_id::DefId; +use hir::def_id::{DefId, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; @@ -1300,17 +1300,20 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -pub(crate) fn compare_const_impl<'tcx>( +/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead +pub(crate) fn raw_compare_const_impl<'tcx>( tcx: TyCtxt<'tcx>, - impl_c: &ty::AssocItem, - impl_c_span: Span, - trait_c: &ty::AssocItem, - impl_trait_ref: ty::TraitRef<'tcx>, -) { + (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), +) -> Result<(), ErrorGuaranteed> { + let impl_const_item = tcx.associated_item(impl_const_item_def); + let trait_const_item = tcx.associated_item(trait_const_item_def); + let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap(); debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); + let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id()); + tcx.infer_ctxt().enter(|infcx| { - let param_env = tcx.param_env(impl_c.def_id); + let param_env = tcx.param_env(impl_const_item_def.to_def_id()); let ocx = ObligationCtxt::new(&infcx); // The below is for the most part highly similar to the procedure @@ -1322,18 +1325,18 @@ pub(crate) fn compare_const_impl<'tcx>( // Create a parameter environment that represents the implementation's // method. - let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local()); + let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_const_item_def); // Compute placeholder form of impl and trait const tys. - let impl_ty = tcx.type_of(impl_c.def_id); - let trait_ty = tcx.bound_type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs); + let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()); + let trait_ty = tcx.bound_type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs); let mut cause = ObligationCause::new( impl_c_span, impl_c_hir_id, ObligationCauseCode::CompareImplItemObligation { - impl_item_def_id: impl_c.def_id.expect_local(), - trait_item_def_id: trait_c.def_id, - kind: impl_c.kind, + impl_item_def_id: impl_const_item_def, + trait_item_def_id: trait_const_item_def, + kind: impl_const_item.kind, }, ); @@ -1358,9 +1361,9 @@ pub(crate) fn compare_const_impl<'tcx>( ); // Locate the Span containing just the type of the offending impl - match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind { + match tcx.hir().expect_impl_item(impl_const_item_def).kind { ImplItemKind::Const(ref ty, _) => cause.span = ty.span, - _ => bug!("{:?} is not a impl const", impl_c), + _ => bug!("{:?} is not a impl const", impl_const_item), } let mut diag = struct_span_err!( @@ -1368,14 +1371,14 @@ pub(crate) fn compare_const_impl<'tcx>( cause.span, E0326, "implemented const `{}` has an incompatible type for trait", - trait_c.name + trait_const_item.name ); - let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| { + let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| { // Add a label to the Span containing just the type of the const match tcx.hir().expect_trait_item(trait_c_def_id).kind { TraitItemKind::Const(ref ty, _) => ty.span, - _ => bug!("{:?} is not a trait const", trait_c), + _ => bug!("{:?} is not a trait const", trait_const_item), } }); @@ -1391,23 +1394,22 @@ pub(crate) fn compare_const_impl<'tcx>( false, false, ); - diag.emit(); - } + return Err(diag.emit()); + }; // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.report_fulfillment_errors(&errors, None, false); - return; + return Err(infcx.report_fulfillment_errors(&errors, None, false)); } + // FIXME return `ErrorReported` if region obligations error? let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( - impl_c.def_id.expect_local(), - &outlives_environment, - ); - }); + infcx + .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment); + Ok(()) + }) } pub(crate) fn compare_ty_impl<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 593a9776bde30..04e8c9c22d159 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -251,6 +251,7 @@ pub fn provide(providers: &mut Providers) { check_mod_item_types, region_scope_tree, collect_trait_impl_trait_tys, + compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl, ..*providers }; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2cd959689e6cf..98eeaad976fe1 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -692,7 +692,6 @@ fn test_unstable_options_tracking_hash() { untracked!(span_free_formats, true); untracked!(temps_dir, Some(String::from("abc"))); untracked!(threads, 99); - untracked!(time, true); untracked!(time_llvm_passes, true); untracked!(time_passes, true); untracked!(trace_macros, true); diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index f7759bec908b4..aee870dd29d65 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -409,7 +409,7 @@ pub fn check_ast_node<'a>( if sess.opts.unstable_opts.no_interleave_lints { for (i, pass) in passes.iter_mut().enumerate() { buffered = - sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| { + sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| { early_lint_node( sess, !pre_expansion && i == 0, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index da6f1c5eeccfd..d4e19ef6b223f 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -425,20 +425,23 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints late_lint_pass_crate(tcx, builtin_lints); } else { for pass in &mut passes { - tcx.sess.prof.extra_verbose_generic_activity("run_late_lint", pass.name()).run(|| { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); + tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run( + || { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }, + ); } let mut passes: Vec<_> = unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); for pass in &mut passes { - tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run( - || { + tcx.sess + .prof + .verbose_generic_activity_with_arg("run_late_module_lint", pass.name()) + .run(|| { late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }, - ); + }); } } } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index d8ce20db37ce9..31705624a7fef 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,7 +1,9 @@ use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; -use rustc_macros::LintDiagnostic; -use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable}; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_middle::ty::{ + self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable, +}; use rustc_span::Span; use rustc_trait_selection::traits; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -117,13 +119,13 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { )) { // If it's a trait bound and an opaque that doesn't satisfy it, // then we can emit a suggestion to add the bound. - let (suggestion, suggest_span) = + let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { - (ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => ( - format!(" + {}", trait_pred.print_modifiers_and_trait_path()), - Some(cx.tcx.def_span(def_id).shrink_to_hi()), - ), - _ => (String::new(), None), + (ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => Some(AddBound { + suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), + trait_ref: trait_pred.print_modifiers_and_trait_path(), + }), + _ => None, }; cx.emit_spanned_lint( OPAQUE_HIDDEN_INFERRED_BOUND, @@ -132,8 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { ty: cx.tcx.mk_opaque(def_id, ty::InternalSubsts::identity_for_item(cx.tcx, def_id)), proj_ty: proj_term, assoc_pred_span, - suggestion, - suggest_span, + add_bound, }, ); } @@ -150,7 +151,19 @@ struct OpaqueHiddenInferredBoundLint<'tcx> { proj_ty: Ty<'tcx>, #[label(lint::specifically)] assoc_pred_span: Span, - #[suggestion_verbose(applicability = "machine-applicable", code = "{suggestion}")] - suggest_span: Option, - suggestion: String, + #[subdiagnostic] + add_bound: Option>, +} + +#[derive(Subdiagnostic)] +#[suggestion_verbose( + lint::opaque_hidden_inferred_bound_sugg, + applicability = "machine-applicable", + code = " + {trait_ref}" +)] +struct AddBound<'tcx> { + #[primary_span] + suggest_span: Span, + #[skip_arg] + trait_ref: TraitPredPrintModifiersAndPath<'tcx>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cf5b365b27c99..334eb953cbcb4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2105,4 +2105,10 @@ rustc_queries! { query permits_zero_init(key: TyAndLayout<'tcx>) -> bool { desc { "checking to see if {:?} permits being left zeroed", key.ty } } + + query compare_assoc_const_impl_item_with_trait_item( + key: (LocalDefId, DefId) + ) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) } + } } diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 0e93f3ce1d646..e96ea682caece 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1067,7 +1067,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>( let _timer = tcx .dep_context() .profiler() - .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::()); + .verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::()); assert!(Q::query_state(tcx).all_inactive()); let cache = Q::query_cache(tcx); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 486c514a4f5c2..8d527c05122d1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -280,14 +280,6 @@ macro_rules! options { ) } -impl Options { - // JUSTIFICATION: defn of the suggested wrapper fn - #[allow(rustc::bad_opt_access)] - pub fn time_passes(&self) -> bool { - self.unstable_opts.time_passes || self.unstable_opts.time - } -} - impl CodegenOptions { // JUSTIFICATION: defn of the suggested wrapper fn #[allow(rustc::bad_opt_access)] @@ -1596,9 +1588,6 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")] threads: usize = (1, parse_threads, [UNTRACKED], "use a thread pool with N threads"), - #[rustc_lint_opt_deny_field_access("use `Session::time_passes` instead of this field")] - time: bool = (false, parse_bool, [UNTRACKED], - "measure time of rustc processes (default: no)"), #[rustc_lint_opt_deny_field_access("use `Session::time_llvm_passes` instead of this field")] time_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each LLVM pass (default: no)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 59b544ce9eb83..5926cdc9dad9a 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -606,10 +606,6 @@ impl Session { self.parse_sess.source_map() } - pub fn time_passes(&self) -> bool { - self.opts.time_passes() - } - /// Returns `true` if internal lints should be added to the lint store - i.e. if /// `-Zunstable-options` is provided and this isn't rustdoc (internal lints can trigger errors /// to be emitted under rustdoc). @@ -927,6 +923,10 @@ impl Session { self.opts.unstable_opts.instrument_mcount } + pub fn time_passes(&self) -> bool { + self.opts.unstable_opts.time_passes + } + pub fn time_llvm_passes(&self) -> bool { self.opts.unstable_opts.time_llvm_passes } @@ -1403,8 +1403,7 @@ pub fn build_session( CguReuseTracker::new_disabled() }; - let prof = - SelfProfilerRef::new(self_profiler, sopts.time_passes(), sopts.unstable_opts.time_passes); + let prof = SelfProfilerRef::new(self_profiler, sopts.unstable_opts.time_passes); let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") { Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 81ca8b646fff1..fe6ebd4b93568 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -186,40 +186,14 @@ fn resolve_associated_item<'tcx>( // a `trait` to an associated `const` definition in an `impl`, where // the definition in the `impl` has the wrong type (for which an // error has already been/will be emitted elsewhere). - // - // NB: this may be expensive, we try to skip it in all the cases where - // we know the error would've been caught (e.g. in an upstream crate). - // - // A better approach might be to just introduce a query (returning - // `Result<(), ErrorGuaranteed>`) for the check that `rustc_hir_analysis` - // performs (i.e. that the definition's type in the `impl` matches - // the declaration in the `trait`), so that we can cheaply check - // here if it failed, instead of approximating it. if leaf_def.item.kind == ty::AssocKind::Const && trait_item_id != leaf_def.item.def_id - && leaf_def.item.def_id.is_local() + && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - let normalized_type_of = |def_id, substs| { - tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id)) - }; - - let original_ty = normalized_type_of(trait_item_id, rcvr_substs); - let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs); - - if original_ty != resolved_ty { - let msg = format!( - "Instance::resolve: inconsistent associated `const` type: \ - was `{}: {}` but resolved to `{}: {}`", - tcx.def_path_str_with_substs(trait_item_id, rcvr_substs), - original_ty, - tcx.def_path_str_with_substs(leaf_def.item.def_id, substs), - resolved_ty, - ); - let span = tcx.def_span(leaf_def.item.def_id); - let reported = tcx.sess.delay_span_bug(span, &msg); - - return Err(reported); - } + tcx.compare_assoc_const_impl_item_with_trait_item(( + leaf_def_item, + trait_item_id, + ))?; } Some(ty::Instance::new(leaf_def.item.def_id, substs)) diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index f97fc4c199dd9..0ddc154fbebbf 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(let_chains)] #![feature(control_flow_enum)] #![feature(never_type)] #![feature(box_patterns)] diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index f1d2d3b30d9e2..da766b67a328f 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -206,9 +206,9 @@ impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef, K, V, Type> { unsafe impl Sync for NodeRef {} -unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef, K, V, Type> {} -unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef, K, V, Type> {} -unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef, K, V, Type> {} unsafe impl Send for NodeRef {} unsafe impl Send for NodeRef {} diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs new file mode 100644 index 0000000000000..8ff5f0abe73dd --- /dev/null +++ b/library/alloc/tests/autotraits.rs @@ -0,0 +1,293 @@ +fn require_sync(_: T) {} +fn require_send_sync(_: T) {} + +struct NotSend(*const ()); +unsafe impl Sync for NotSend {} + +#[test] +fn test_btree_map() { + // Tests of this form are prone to https://github.com/rust-lang/rust/issues/64552. + // + // In theory the async block's future would be Send if the value we hold + // across the await point is Send, and Sync if the value we hold across the + // await point is Sync. + // + // We test autotraits in this convoluted way, instead of a straightforward + // `require_send_sync::()`, because the interaction with + // generators exposes some current limitations in rustc's ability to prove a + // lifetime bound on the erased generator witness types. See the above link. + // + // A typical way this would surface in real code is: + // + // fn spawn(_: T) {} + // + // async fn f() { + // let map = BTreeMap::>::new(); + // for _ in &map { + // async {}.await; + // } + // } + // + // fn main() { + // spawn(f()); + // } + // + // where with some unintentionally overconstrained Send impls in liballoc's + // internals, the future might incorrectly not be Send even though every + // single type involved in the program is Send and Sync. + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + // Testing like this would not catch all issues that the above form catches. + require_send_sync(None::>); + + require_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::< + alloc::collections::btree_map::DrainFilter< + '_, + &u32, + &u32, + fn(&&u32, &mut &u32) -> bool, + >, + >; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); +} + +#[test] +fn test_btree_set() { + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None:: bool>>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); +} + +#[test] +fn test_binary_heap() { + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); +} + +#[test] +fn test_linked_list() { + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + // FIXME + /* + require_send_sync(async { + let _v = + None:: bool>>; + async {}.await; + }); + */ + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); +} + +#[test] +fn test_vec_deque() { + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); + + require_send_sync(async { + let _v = None::>; + async {}.await; + }); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f30ebd77e2466..ffc5ca7a5c6cc 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -2,6 +2,7 @@ #![feature(alloc_layout_extra)] #![feature(assert_matches)] #![feature(box_syntax)] +#![feature(btree_drain_filter)] #![feature(cow_is_borrowed)] #![feature(const_box)] #![feature(const_convert)] @@ -14,6 +15,8 @@ #![feature(core_intrinsics)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(linked_list_cursors)] +#![feature(map_try_insert)] #![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] @@ -49,6 +52,7 @@ use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; mod arc; +mod autotraits; mod borrow; mod boxed; mod btree_set_hash; diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index e96f8b0d3125f..776d73b98c4f1 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -67,7 +67,7 @@ fn main() { if target == "all" || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name) { - cmd.arg("-Ztime"); + cmd.arg("-Ztime-passes"); } } } diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 79cdfb82e417e..2d12cf382b160 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -300,7 +300,7 @@ _Note:_ The order of these lint level arguments is taken into account, see [lint ## `-Z`: set unstable options This flag will allow you to set unstable options of rustc. In order to set multiple options, -the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time`. +the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time-passes`. Specifying options with -Z is only available on nightly. To view all available options run: `rustc -Z help`. diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 62ba984acc961..6f9cc026675b6 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -58,7 +58,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( let emit_crate = options.should_emit_crate(); let (mut format_renderer, krate) = prof - .extra_verbose_generic_activity("create_renderer", T::descr()) + .verbose_generic_activity_with_arg("create_renderer", T::descr()) .run(|| T::init(krate, options, cache, tcx))?; if !emit_crate { @@ -92,6 +92,6 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( .run(|| cx.item(item))?; } } - prof.extra_verbose_generic_activity("renderer_after_krate", T::descr()) + prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr()) .run(|| format_renderer.after_krate()) } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b86b8f9dbf864..28e968c9ff5f9 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -914,6 +914,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ font-size: 1rem; width: 100%; background-color: var(--button-background-color); + color: var(--search-color); } .search-input:focus { border-color: var(--search-input-focused-border-color); diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 7245dce6ed6e3..0975d497cb23c 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -40,6 +40,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-result-link-focus-background-color: #3c3c3c; --stab-background-color: #314559; --stab-code-color: #e6e1cf; + --search-color: #fff; } .slider { @@ -149,10 +150,6 @@ details.rustdoc-toggle > summary::before { filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%); } -.search-input { - color: #fff; -} - .module-item .stab, .import-item .stab { color: #000; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 9d5406e65a8b9..ee2a9ec8a0bee 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -35,6 +35,7 @@ --search-result-link-focus-background-color: #616161; --stab-background-color: #314559; --stab-code-color: #e6e1cf; + --search-color: #111; } .slider { @@ -72,10 +73,6 @@ details.rustdoc-toggle > summary::before { filter: invert(100%); } -.search-input { - color: #111; -} - #crate-search-div::after { /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%); diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index b63895e56c687..7287d5b62123b 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -35,6 +35,7 @@ --search-result-link-focus-background-color: #ccc; --stab-background-color: #fff5d6; --stab-code-color: #000; + --search-color: #000; } .slider { diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 25d5c6e4ad2b9..65536cb3aa135 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -170,7 +170,6 @@ -Z thinlto=val -- enable ThinLTO when possible -Z thir-unsafeck=val -- use the THIR unsafety checker (default: no) -Z threads=val -- use a thread pool with N threads - -Z time=val -- measure time of rustc processes (default: no) -Z time-llvm-passes=val -- measure time of each LLVM pass (default: no) -Z time-passes=val -- measure time of each rustc pass (default: no) -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index de1d9589e9961..742b81535dfdf 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 | LL | const NAME: &'a str = "unit"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected reference `&'static str` found reference `&'a str` diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_1.rs b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs new file mode 100644 index 0000000000000..4dc6c2e47a9ea --- /dev/null +++ b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MyTrait { + type ArrayType; + const SIZE: usize; + const ARRAY: Self::ArrayType; +} +impl MyTrait for () { + type ArrayType = [u8; Self::SIZE]; + const SIZE: usize = 4; + const ARRAY: [u8; Self::SIZE] = [1, 2, 3, 4]; +} + +fn main() { + let _ = <() as MyTrait>::ARRAY; +} diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_2.rs b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs new file mode 100644 index 0000000000000..539becfdc7c82 --- /dev/null +++ b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: fn(&'static u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32) = |_| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_3.rs b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs new file mode 100644 index 0000000000000..17bcc8fe5768c --- /dev/null +++ b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: for<'a, 'b> fn(&'a u32, &'b u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32, &'a u32) = |_, _| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/src/test/ui/lint/issue-102705.rs b/src/test/ui/lint/issue-102705.rs new file mode 100644 index 0000000000000..5bcc8950adafb --- /dev/null +++ b/src/test/ui/lint/issue-102705.rs @@ -0,0 +1,22 @@ +// check-pass + +#![allow(opaque_hidden_inferred_bound)] +#![allow(dead_code)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl R> Trait for F { + type Assoc = R; +} + +fn foo() -> impl Trait { + || 42 +} + +fn main() {} diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index ae0ffd904e799..cf1c52ba7cc43 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait --> $DIR/trait-associated-constant.rs:21:5 | LL | const AC: Option<&'c str> = None; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected enum `Option<&'b str>` found enum `Option<&'c str>`