From afd45c2e10d9a5dbb277852384bb3d2245239f63 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 8 Apr 2023 14:24:16 +0900 Subject: [PATCH 01/11] Stabilize IsTerminal closes: https://github.com/rust-lang/rust/issues/98070 --- compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_errors/src/lib.rs | 1 - compiler/rustc_log/src/lib.rs | 1 - library/std/src/io/mod.rs | 2 +- library/std/src/io/stdio.rs | 5 +++-- library/std/src/lib.rs | 1 - library/std/src/os/fd/owned.rs | 2 +- library/std/src/os/windows/io/handle.rs | 2 +- library/test/src/lib.rs | 1 - src/librustdoc/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - src/tools/miri/tests/pass/shims/fs.rs | 1 - src/tools/miri/tests/pass/shims/io.rs | 2 -- 13 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 730d41ab962f8..ba5873d79a299 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(is_terminal)] #![feature(lazy_cell)] #![feature(decl_macro)] #![recursion_limit = "256"] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9866a9bffe0e1..cee62d2375441 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,7 +6,6 @@ #![feature(array_windows)] #![feature(drain_filter)] #![feature(if_let_guard)] -#![feature(is_terminal)] #![feature(adt_const_params)] #![feature(let_chains)] #![feature(never_type)] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 21f6a404a0153..3cbb2c21e289e 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -40,7 +40,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![feature(is_terminal)] use std::env::{self, VarError}; use std::fmt::{self, Display}; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 4b31c552eedd2..020c723925aeb 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -268,7 +268,7 @@ pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] pub use self::stdio::set_output_capture; -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] pub use self::stdio::IsTerminal; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 1a3200a5c62b8..b2c57b8ddc78e 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1047,7 +1047,7 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) { } /// Trait to determine if a descriptor/handle refers to a terminal/tty. -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] pub trait IsTerminal: crate::sealed::Sealed { /// Returns `true` if the descriptor/handle refers to a terminal/tty. /// @@ -1063,6 +1063,7 @@ pub trait IsTerminal: crate::sealed::Sealed { /// Note that this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] fn is_terminal(&self) -> bool; } @@ -1071,7 +1072,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 736b3c0497c46..71f3576c93d4b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -254,7 +254,6 @@ #![feature(exhaustive_patterns)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] -#![feature(is_terminal)] #![feature(lang_items)] #![feature(let_chains)] #![feature(linkage)] diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index a40d39c5e44f5..6a6e6f33158fc 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -201,7 +201,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 1dfecc57338a7..f6622874625fc 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -389,7 +389,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 88d8e5fe97ad7..9fb31ed7663d0 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -17,7 +17,6 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] #![feature(internal_output_capture)] -#![feature(is_terminal)] #![feature(staged_api)] #![feature(process_exitcode_internals)] #![feature(panic_can_unwind)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 79f53ee57cc9d..8ab212099e344 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -7,7 +7,6 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] -#![feature(is_terminal)] #![feature(let_chains)] #![feature(test)] #![feature(never_type)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index fb4e59acd001d..dcdec0627b709 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -7,7 +7,6 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(local_key_cell_methods)] -#![feature(is_terminal)] #![feature(round_ties_even)] // Configure clippy and other lints #![allow( diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 7a9974f393895..e379288de01cb 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -3,7 +3,6 @@ #![feature(io_error_more)] #![feature(io_error_uncategorized)] -#![feature(is_terminal)] use std::collections::HashMap; use std::ffi::{c_char, OsString}; diff --git a/src/tools/miri/tests/pass/shims/io.rs b/src/tools/miri/tests/pass/shims/io.rs index 4d43549a930be..295723957a426 100644 --- a/src/tools/miri/tests/pass/shims/io.rs +++ b/src/tools/miri/tests/pass/shims/io.rs @@ -1,5 +1,3 @@ -#![feature(is_terminal)] - use std::io::IsTerminal; fn main() { From 5eb0528483ddb7614578fe5ef4b1104047b10ce6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 11 Apr 2023 17:17:25 +0000 Subject: [PATCH 02/11] Erase lifetimes above ty::INNERMOST when probing ambiguous types --- .../rustc_hir_analysis/src/astconv/mod.rs | 20 ++++++------------- .../missing-assoc-item.stderr | 7 ++++++- tests/ui/typeck/issue-110052.rs | 12 +++++++++++ tests/ui/typeck/issue-110052.stderr | 9 +++++++++ 4 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 tests/ui/typeck/issue-110052.rs create mode 100644 tests/ui/typeck/issue-110052.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index acca3fa264187..96a7acc3c27bf 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2514,24 +2514,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id), ); - // I guess we don't need to make a universe unless we need it, - // but also we're on the error path, so it doesn't matter here. - let universe = infcx.create_next_universe(); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); + // FIXME: Don't bother dealing with non-lifetime binders here... + if value.has_escaping_bound_vars() { + return false; + } infcx .can_eq( ty::ParamEnv::empty(), impl_.self_ty(), - tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate { - regions: &mut |_| tcx.lifetimes.re_erased, - types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType { - universe, - bound: bv, - }), - consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst { - universe, - bound: bv, - }, ty), - }) + value, ) }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr index be6955c111e83..d985386423d29 100644 --- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr @@ -11,7 +11,12 @@ error[E0223]: ambiguous associated type --> $DIR/missing-assoc-item.rs:6:12 | LL | for B::Item: Send, - | ^^^^^^^ help: use the fully-qualified path: `::Item` + | ^^^^^^^ + | +help: if there were a trait named `Example` with associated type `Item` implemented for `B`, you could use the fully-qualified path + | +LL | for ::Item: Send, + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/typeck/issue-110052.rs b/tests/ui/typeck/issue-110052.rs new file mode 100644 index 0000000000000..f124b58b5b605 --- /dev/null +++ b/tests/ui/typeck/issue-110052.rs @@ -0,0 +1,12 @@ +// Makes sure we deal with escaping lifetimes *above* INNERMOST when +// suggesting trait for ambiguous associated type. + +impl Validator for () +where + for<'iter> dyn Validator<<&'iter I>::Item>:, + //~^ ERROR ambiguous associated type +{} + +pub trait Validator {} + +fn main() {} diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr new file mode 100644 index 0000000000000..0c15c03a7408d --- /dev/null +++ b/tests/ui/typeck/issue-110052.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-110052.rs:6:30 + | +LL | for<'iter> dyn Validator<<&'iter I>::Item>:, + | ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. From a19adefa0e5aca0aabca2430530577ee140e4efa Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 10:24:36 +0200 Subject: [PATCH 03/11] region error cleanup - require `TypeErrCtxt` to always result in an error - move `resolve_regions_and_report_errors` to the `ObligationCtxt` - merge `process_registered_region_obligations` into `resolve_regions` --- .../rustc_hir_analysis/src/check/check.rs | 7 +- .../src/check/compare_impl_item.rs | 40 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 11 +- .../src/coherence/builtin.rs | 6 +- .../src/impl_wf_check/min_specialization.rs | 3 +- .../src/infer/error_reporting/mod.rs | 30 +++- compiler/rustc_infer/src/infer/mod.rs | 142 +----------------- .../rustc_infer/src/infer/outlives/mod.rs | 104 ++++++++++++- .../src/infer/outlives/obligations.rs | 47 ++---- .../src/traits/auto_trait.rs | 3 +- .../src/traits/coherence.rs | 3 - .../src/traits/engine.rs | 19 +++ .../rustc_trait_selection/src/traits/misc.rs | 4 - 13 files changed, 183 insertions(+), 236 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8617bca082589..0bb98fdf2a23e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -452,11 +452,8 @@ fn check_opaque_meets_bounds<'tcx>( hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { - let outlives_environment = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors( - defining_use_anchor, - &outlives_environment, - ); + let outlives_env = OutlivesEnvironment::new(param_env); + let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env); } } // Clean up after ourselves diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f6c2004c4a672..5d119a7737a4c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -332,10 +332,6 @@ fn compare_method_predicate_entailment<'tcx>( param_env, infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), ); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - outlives_env.param_env, - ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT @@ -722,18 +718,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( return Err(reported); } + let collected_types = collector.types; + // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::with_bounds( + let outlives_env = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), ); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?; + ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; let mut collected_tys = FxHashMap::default(); - for (def_id, (ty, substs)) in collector.types { + for (def_id, (ty, substs)) in collected_types { match infcx.fully_resolve(ty) { Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the @@ -1742,11 +1738,8 @@ pub(super) fn compare_impl_const_raw( return Err(infcx.err_ctxt().report_fulfillment_errors(&errors)); } - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env) } pub(super) fn compare_impl_ty<'tcx>( @@ -1845,13 +1838,8 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } /// Validate that `ProjectionCandidate`s created for this associated type will @@ -2063,14 +2051,8 @@ pub(super) fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types); - let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c03621fcfb224..53197bc849106 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -114,11 +114,9 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( return; } - let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -680,12 +678,7 @@ fn resolve_regions_with_wf_tys<'tcx>( add_constraints(&infcx, region_bound_pairs); - infcx.process_registered_region_obligations( - outlives_environment.region_bound_pairs(), - param_env, - ); let errors = infcx.resolve_regions(&outlives_environment); - debug!(?errors, "errors"); // If we were able to prove that the type outlives the region without diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ac7c68d9c4b30..0f40cca9427b4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -354,9 +354,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -592,7 +590,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 35785e81ff497..eb2fc395223ed 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -180,8 +180,7 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = - infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7901bc9402122..f6bed12ee2d43 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -74,6 +74,7 @@ use rustc_middle::ty::{ self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; +use rustc_span::DUMMY_SP; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::{ControlFlow, Deref}; @@ -113,7 +114,11 @@ fn escape_literal(s: &str) -> String { /// A helper for building type related errors. The `typeck_results` /// field is only populated during an in-progress typeck. -/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`. +/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`. +/// +/// You must only create this if you intend to actually emit an error. +/// This provides a lot of utility methods which should not be used +/// during the happy path. pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option>>, @@ -125,6 +130,19 @@ pub struct TypeErrCtxt<'a, 'tcx> { Box) -> Vec<(Ty<'tcx>, Vec>)> + 'a>, } +impl Drop for TypeErrCtxt<'_, '_> { + fn drop(&mut self) { + if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() { + // ok, emitted an error. + } else { + self.infcx + .tcx + .sess + .delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation"); + } + } +} + impl TypeErrCtxt<'_, '_> { /// This is just to avoid a potential footgun of accidentally /// dropping `typeck_results` by calling `InferCtxt::err_ctxt` @@ -419,7 +437,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, generic_param_scope: LocalDefId, errors: &[RegionResolutionError<'tcx>], - ) { + ) -> ErrorGuaranteed { + if let Some(guaranteed) = self.infcx.tainted_by_errors() { + return guaranteed; + } + debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them @@ -499,6 +521,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } } + + self.tcx + .sess + .delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors") } // This method goes through all the errors and try to group certain types diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b4f2ad0bb3433..66f51328bbe7c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -45,8 +45,7 @@ use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; use self::free_regions::RegionRelations; use self::lexical_region_resolve::LexicalRegionResolutions; -use self::outlives::env::OutlivesEnvironment; -use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; +use self::region_constraints::{GenericKind, VarInfos, VerifyBound}; use self::region_constraints::{ RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, }; @@ -1213,95 +1212,6 @@ impl<'tcx> InferCtxt<'tcx> { self.tainted_by_errors.set(Some(e)); } - pub fn skip_region_resolution(&self) { - let (var_infos, _) = { - let mut inner = self.inner.borrow_mut(); - let inner = &mut *inner; - // Note: `inner.region_obligations` may not be empty, because we - // didn't necessarily call `process_registered_region_obligations`. - // This is okay, because that doesn't introduce new vars. - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() - }; - - let lexical_region_resolutions = LexicalRegionResolutions { - values: rustc_index::vec::IndexVec::from_elem_n( - crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), - var_infos.len(), - ), - }; - - let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); - assert!(old_value.is_none()); - } - - /// Process the region constraints and return any errors that - /// result. After this, no more unification operations should be - /// done -- or the compiler will panic -- but it is legal to use - /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions( - &self, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Vec> { - let (var_infos, data) = { - let mut inner = self.inner.borrow_mut(); - let inner = &mut *inner; - assert!( - self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(), - "region_obligations not empty: {:#?}", - inner.region_obligations - ); - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() - }; - - let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); - - let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); - - let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); - assert!(old_value.is_none()); - - errors - } - /// Obtains (and clears) the current set of region - /// constraints. The inference context is still usable: further - /// unifications will simply add new constraints. - /// - /// This method is not meant to be used with normal lexical region - /// resolution. Rather, it is used in the NLL mode as a kind of - /// interim hack: basically we run normal type-check and generate - /// region constraints as normal, but then we take them and - /// translate them into the form that the NLL solver - /// understands. See the NLL module for mode details. - pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { - assert!( - self.inner.borrow().region_obligations.is_empty(), - "region_obligations not empty: {:#?}", - self.inner.borrow().region_obligations - ); - - self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data() - } - - /// Gives temporary access to the region constraint data. - pub fn with_region_constraints( - &self, - op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, - ) -> R { - let mut inner = self.inner.borrow_mut(); - op(inner.unwrap_region_constraints().data()) - } - pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; @@ -1754,56 +1664,6 @@ impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> { } impl<'tcx> TypeErrCtxt<'_, 'tcx> { - /// Processes registered region obliations and resolves regions, reporting - /// any errors if any were raised. Prefer using this function over manually - /// calling `resolve_regions_and_report_errors`. - pub fn check_region_obligations_and_report_errors( - &self, - generic_param_scope: LocalDefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Result<(), ErrorGuaranteed> { - self.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - outlives_env.param_env, - ); - - self.resolve_regions_and_report_errors(generic_param_scope, outlives_env) - } - - /// Process the region constraints and report any errors that - /// result. After this, no more unification operations should be - /// done -- or the compiler will panic -- but it is legal to use - /// `resolve_vars_if_possible` as well as `fully_resolve`. - /// - /// Make sure to call [`InferCtxt::process_registered_region_obligations`] - /// first, or preferably use [`TypeErrCtxt::check_region_obligations_and_report_errors`] - /// to do both of these operations together. - pub fn resolve_regions_and_report_errors( - &self, - generic_param_scope: LocalDefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Result<(), ErrorGuaranteed> { - let errors = self.resolve_regions(outlives_env); - - if let None = self.tainted_by_errors() { - // As a heuristic, just skip reporting region errors - // altogether if other errors have been reported while - // this infcx was in use. This is totally hokey but - // otherwise we have a hard time separating legit region - // errors from silly ones. - self.report_region_errors(generic_param_scope, &errors); - } - - if errors.is_empty() { - Ok(()) - } else { - Err(self - .tcx - .sess - .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")) - } - } - // [Note-Type-error-reporting] // An invariant is that anytime the expected or actual type is Error (the special // error type, meaning that an error occurred when typechecking this expression), diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 048dad3a48bc2..21907c4b42340 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,4 +1,11 @@ //! Various code related to computing outlives relations. +use self::env::OutlivesEnvironment; +use super::region_constraints::RegionConstraintData; +use super::{InferCtxt, RegionResolutionError}; +use crate::infer::free_regions::RegionRelations; +use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions}; +use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::ty; pub mod components; pub mod env; @@ -6,9 +13,6 @@ pub mod obligations; pub mod test_type_match; pub mod verify; -use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty; - #[instrument(level = "debug", skip(param_env), ret)] pub fn explicit_outlives_bounds<'tcx>( param_env: ty::ParamEnv<'tcx>, @@ -39,3 +43,97 @@ pub fn explicit_outlives_bounds<'tcx>( ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)), }) } + +impl<'tcx> InferCtxt<'tcx> { + pub fn skip_region_resolution(&self) { + let (var_infos, _) = { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + // Note: `inner.region_obligations` may not be empty, because we + // didn't necessarily call `process_registered_region_obligations`. + // This is okay, because that doesn't introduce new vars. + inner + .region_constraint_storage + .take() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .into_infos_and_data() + }; + + let lexical_region_resolutions = LexicalRegionResolutions { + values: rustc_index::vec::IndexVec::from_elem_n( + crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), + var_infos.len(), + ), + }; + + let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + assert!(old_value.is_none()); + } + + /// Process the region constraints and return any errors that + /// result. After this, no more unification operations should be + /// done -- or the compiler will panic -- but it is legal to use + /// `resolve_vars_if_possible` as well as `fully_resolve`. + pub fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.process_registered_region_obligations(outlives_env); + + let (var_infos, data) = { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + assert!( + self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(), + "region_obligations not empty: {:#?}", + inner.region_obligations + ); + inner + .region_constraint_storage + .take() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .into_infos_and_data() + }; + + let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); + + let (lexical_region_resolutions, errors) = + lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); + + let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + assert!(old_value.is_none()); + + errors + } + + /// Obtains (and clears) the current set of region + /// constraints. The inference context is still usable: further + /// unifications will simply add new constraints. + /// + /// This method is not meant to be used with normal lexical region + /// resolution. Rather, it is used in the NLL mode as a kind of + /// interim hack: basically we run normal type-check and generate + /// region constraints as normal, but then we take them and + /// translate them into the form that the NLL solver + /// understands. See the NLL module for mode details. + pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { + assert!( + self.inner.borrow().region_obligations.is_empty(), + "region_obligations not empty: {:#?}", + self.inner.borrow().region_obligations + ); + + self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data() + } + + /// Gives temporary access to the region constraint data. + pub fn with_region_constraints( + &self, + op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, + ) -> R { + let mut inner = self.inner.borrow_mut(); + op(inner.unwrap_region_constraints().data()) + } +} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index bbe7d4c63f794..ccf11c61b573b 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -72,6 +72,8 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt}; use smallvec::smallvec; +use super::env::OutlivesEnvironment; + impl<'tcx> InferCtxt<'tcx> { /// Registers that the given region obligation must be resolved /// from within the scope of `body_id`. These regions are enqueued @@ -112,39 +114,17 @@ impl<'tcx> InferCtxt<'tcx> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } - /// NOTE: Prefer using `TypeErrCtxt::check_region_obligations_and_report_errors` - /// instead of calling this directly. - /// /// Process the region obligations that must be proven (during /// `regionck`) for the given `body_id`, given information about - /// the region bounds in scope and so forth. This function must be - /// invoked for all relevant body-ids before region inference is - /// done (or else an assert will fire). + /// the region bounds in scope and so forth. /// /// See the `region_obligations` field of `InferCtxt` for some /// comments about how this function fits into the overall expected /// flow of the inferencer. The key point is that it is /// invoked after all type-inference variables have been bound -- - /// towards the end of regionck. This also ensures that the - /// region-bound-pairs are available (see comments above regarding - /// closures). - /// - /// # Parameters - /// - /// - `region_bound_pairs_map`: the set of region bounds implied by - /// the parameters and where-clauses. In particular, each pair - /// `('a, K)` in this list tells us that the bounds in scope - /// indicate that `K: 'a`, where `K` is either a generic - /// parameter like `T` or a projection like `T::Item`. - /// - `param_env` is the parameter environment for the enclosing function. - /// - `body_id` is the body-id whose region obligations are being - /// processed. - #[instrument(level = "debug", skip(self, region_bound_pairs))] - pub fn process_registered_region_obligations( - &self, - region_bound_pairs: &RegionBoundPairs<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) { + /// right before lexical region resolution. + #[instrument(level = "debug", skip(self, outlives_env))] + pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { assert!( !self.in_snapshot.get(), "cannot process registered region obligations in a snapshot" @@ -153,15 +133,16 @@ impl<'tcx> InferCtxt<'tcx> { let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - debug!( - "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", - sup_type, sub_region, origin - ); - + debug!(?sup_type, ?sub_region, ?origin); let sup_type = self.resolve_vars_if_possible(sup_type); - let outlives = - &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); + let outlives = &mut TypeOutlives::new( + self, + self.tcx, + &outlives_env.region_bound_pairs(), + None, + outlives_env.param_env, + ); let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a53d414be9e7a..fd45ef99aa9d0 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -187,7 +187,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); } - infcx.process_registered_region_obligations(&Default::default(), full_env); + let outlives_env = OutlivesEnvironment::new(full_env); + infcx.process_registered_region_obligations(&outlives_env); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 53d4f95e9e30f..3c918b6028d47 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -405,9 +405,6 @@ fn resolve_negative_obligation<'tcx>( param_env, infcx.implied_bounds_tys(param_env, body_def_id, wf_tys), ); - - infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - infcx.resolve_regions(&outlives_env).is_empty() } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 8acc31cd410bd..d2b39ed226f04 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -6,11 +6,13 @@ use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::NormalizeExt; use rustc_data_structures::fx::FxIndexSet; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::query::Fallible; use rustc_infer::traits::{ @@ -181,6 +183,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.engine.borrow_mut().select_all_or_error(self.infcx) } + /// Resolves regions and reports errors. + /// + /// Takes ownership of the context as doing trait solving afterwards + /// will result in region constraints getting ignored. + pub fn resolve_regions_and_report_errors( + self, + generic_param_scope: LocalDefId, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Result<(), ErrorGuaranteed> { + let errors = self.infcx.resolve_regions(&outlives_env); + if errors.is_empty() { + Ok(()) + } else { + Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors)) + } + } + pub fn assumed_wf_types( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 0bde43c54df99..af567c074384e 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -117,10 +117,6 @@ pub fn type_allowed_to_implement_copy<'tcx>( FxIndexSet::from_iter([self_type]), ), ); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - param_env, - ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { infringing.push((field, ty, InfringingFieldsReason::Regions(errors))); From cc82ccb145f2056854b499d5033be1a06ddfa29c Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 10:31:41 +0200 Subject: [PATCH 04/11] `#[must_use]` for fns returning a list of errors --- compiler/rustc_infer/src/infer/outlives/mod.rs | 1 + compiler/rustc_infer/src/traits/engine.rs | 2 ++ compiler/rustc_trait_selection/src/traits/engine.rs | 2 ++ .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 +++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 21907c4b42340..9a9a1696b0063 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -75,6 +75,7 @@ impl<'tcx> InferCtxt<'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. + #[must_use] pub fn resolve_regions( &self, outlives_env: &OutlivesEnvironment<'tcx>, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index f75344f20b6d9..a188bb2388271 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -36,6 +36,7 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); + #[must_use] fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; fn collect_remaining_errors(&mut self) -> Vec>; @@ -58,6 +59,7 @@ pub trait TraitEngineExt<'tcx> { obligations: impl IntoIterator>, ); + #[must_use] fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d2b39ed226f04..2beebe94b6d1d 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -175,10 +175,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + #[must_use] pub fn select_where_possible(&self) -> Vec> { self.engine.borrow_mut().select_where_possible(self.infcx) } + #[must_use] pub fn select_all_or_error(&self) -> Vec> { self.engine.borrow_mut().select_all_or_error(self.infcx) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6ebf056f0e837..6790d7b76a3ad 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1763,7 +1763,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. - ocx.select_where_possible(); + // + // we intentionally errors from normalization here. + let _ = ocx.select_where_possible(); if let Err(new_err) = ocx.eq_exp( &obligation.cause, From cdd982955623f697f759f548ce11f886a413f4f6 Mon Sep 17 00:00:00 2001 From: marc0246 <40955683+marc0246@users.noreply.github.com> Date: Wed, 12 Apr 2023 19:21:40 +0200 Subject: [PATCH 05/11] Fix btree `CursorMut::insert_after` check --- library/alloc/src/collections/btree/map.rs | 2 +- .../alloc/src/collections/btree/map/tests.rs | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 61db46314b780..da675379cd58b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -3183,7 +3183,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { panic!("key must be ordered above the current element"); } } - if let Some((next, _)) = self.peek_prev() { + if let Some((next, _)) = self.peek_next() { if &key >= next { panic!("key must be ordered below the next element"); } diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 76c2f27b46634..4311f21c925cd 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -2385,3 +2385,67 @@ fn test_cursor_mut() { assert_eq!(cur.key(), Some(&4)); assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')])); } + +#[should_panic(expected = "key must be ordered above the previous element")] +#[test] +fn test_cursor_mut_insert_before_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(0, 'd'); +} + +#[should_panic(expected = "key must be ordered above the previous element")] +#[test] +fn test_cursor_mut_insert_before_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(1, 'd'); +} + +#[should_panic(expected = "key must be ordered below the current element")] +#[test] +fn test_cursor_mut_insert_before_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(2, 'd'); +} + +#[should_panic(expected = "key must be ordered below the current element")] +#[test] +fn test_cursor_mut_insert_before_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(3, 'd'); +} + +#[should_panic(expected = "key must be ordered above the current element")] +#[test] +fn test_cursor_mut_insert_after_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(1, 'd'); +} + +#[should_panic(expected = "key must be ordered above the current element")] +#[test] +fn test_cursor_mut_insert_after_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(2, 'd'); +} + +#[should_panic(expected = "key must be ordered below the next element")] +#[test] +fn test_cursor_mut_insert_after_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(3, 'd'); +} + +#[should_panic(expected = "key must be ordered below the next element")] +#[test] +fn test_cursor_mut_insert_after_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(4, 'd'); +} From c0d3d32922d308088dd176d216d6c7409374c70b Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 22:07:07 +0200 Subject: [PATCH 06/11] fix comment --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6790d7b76a3ad..81ab5b9f05769 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1764,7 +1764,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. // - // we intentionally errors from normalization here. + // we intentionally drop errors from normalization here, + // since the normalization is just done to improve the error message. let _ = ocx.select_where_possible(); if let Err(new_err) = ocx.eq_exp( From 9b0ceb4395fbc24bb5aff18b118487cb551167ba Mon Sep 17 00:00:00 2001 From: Justin Symonds Date: Wed, 12 Apr 2023 18:21:56 -0700 Subject: [PATCH 07/11] Update unwind_safe.rs Typo in the documentation. --- library/core/src/panic/unwind_safe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 9a6153f1253c5..7e7b6b4dbe9b1 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -28,7 +28,7 @@ use crate::task::{Context, Poll}; /// 2. This broken invariant is then later observed. /// /// Typically in Rust, it is difficult to perform step (2) because catching a -/// panic involves either spawning a thread (which in turns makes it difficult +/// panic involves either spawning a thread (which in turn makes it difficult /// to later witness broken invariants) or using the `catch_unwind` function in this /// module. Additionally, even if an invariant is witnessed, it typically isn't a /// problem in Rust because there are no uninitialized values (like in C or C++). From c802694bdaded1ee655a08c3ecf03cf57bc4d60f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:36:03 +1000 Subject: [PATCH 08/11] Make `Region::as_var` infallible. It's what all the call sites require. --- compiler/rustc_borrowck/src/lib.rs | 8 ++------ compiler/rustc_borrowck/src/type_check/relate_tys.rs | 11 ++--------- compiler/rustc_middle/src/ty/sty.rs | 6 +++--- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3d876155fc952..043ccaa027156 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -507,9 +507,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { F: Fn() -> RegionCtxt, { let next_region = self.infcx.next_region_var(origin); - let vid = next_region - .as_var() - .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + let vid = next_region.as_var(); if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); @@ -531,9 +529,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { F: Fn() -> RegionCtxt, { let next_region = self.infcx.next_nll_region_var(origin.clone()); - let vid = next_region - .as_var() - .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + let vid = next_region.as_var(); if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 6b64e65518f5b..7e6d17ec3437e 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -131,13 +131,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), }; - let reg_var = - reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - debug!(?reg_var); - var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info)); + var_to_origin.insert(reg.as_var(), RegionCtxt::Placeholder(reg_info)); } reg @@ -150,12 +146,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> universe, ); - let reg_var = - reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(reg_var, RegionCtxt::Existential(None)); + var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); } reg diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 086ceebd24d60..bbf6430a5ae70 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1772,10 +1772,10 @@ impl<'tcx> Region<'tcx> { matches!(self.kind(), ty::ReVar(_)) } - pub fn as_var(self) -> Option { + pub fn as_var(self) -> RegionVid { match self.kind() { - ty::ReVar(vid) => Some(vid), - _ => None, + ty::ReVar(vid) => vid, + _ => bug!("expected region {:?} to be of kind ReVar", self), } } } From 411422f2b9b0861f416d18f1ab9ca079ac01bb08 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:26:05 +1000 Subject: [PATCH 09/11] Remove `impl ToRegionVid for RegionVid`. It's weird and unnecessary. --- compiler/rustc_borrowck/src/dataflow.rs | 6 ++---- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_borrowck/src/nll.rs | 6 ------ .../rustc_borrowck/src/region_infer/mod.rs | 21 ++++++++----------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 2cbd2e3bc0d86..94939c7e4cd72 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -11,9 +11,7 @@ use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill} use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; -use crate::{ - places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid, -}; +use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// A tuple with named fields that can hold either the results or the transient state of the /// dataflow analyses used by the borrow checker. @@ -242,7 +240,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { ) -> Self { let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx); for (borrow_index, borrow_data) in borrow_set.iter_enumerated() { - let borrow_region = borrow_data.region.to_region_vid(); + let borrow_region = borrow_data.region; let location = borrow_data.reserve_location; prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 043ccaa027156..a4b285a34fa46 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -94,7 +94,7 @@ pub mod consumers; use borrow_set::{BorrowData, BorrowSet}; use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows}; -use nll::{PoloniusOutput, ToRegionVid}; +use nll::PoloniusOutput; use place_ext::PlaceExt; use places_conflict::{places_conflict, PlaceConflictBias}; use region_infer::RegionInferenceContext; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 06ecbdb1707c5..8b5ff999e9b3d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -459,12 +459,6 @@ impl<'tcx> ToRegionVid for Region<'tcx> { } } -impl ToRegionVid for RegionVid { - fn to_region_vid(self) -> RegionVid { - self - } -} - pub(crate) trait ConstraintDescription { fn description(&self) -> &'static str; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f67af4584a4a5..ce6f3690e1904 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -27,7 +27,7 @@ use crate::{ }, diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, - nll::{PoloniusOutput, ToRegionVid}, + nll::PoloniusOutput, region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, @@ -593,14 +593,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Returns `true` if the region `r` contains the point `p`. /// /// Panics if called before `solve()` executes, - pub(crate) fn region_contains(&self, r: impl ToRegionVid, p: impl ToElementIndex) -> bool { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + pub(crate) fn region_contains(&self, r: RegionVid, p: impl ToElementIndex) -> bool { + let scc = self.constraint_sccs.scc(r); self.scc_values.contains(scc, p) } /// Returns access to the value of `r` for debugging purposes. pub(crate) fn region_value_str(&self, r: RegionVid) -> String { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_values.region_value_str(scc) } @@ -608,24 +608,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { &'a self, r: RegionVid, ) -> impl Iterator + 'a { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_values.placeholders_contained_in(scc) } /// Returns access to the value of `r` for debugging purposes. pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_universes[scc] } /// Once region solving has completed, this function will return /// the member constraints that were applied to the value of a given /// region `r`. See `AppliedMemberConstraint`. - pub(crate) fn applied_member_constraints( - &self, - r: impl ToRegionVid, - ) -> &[AppliedMemberConstraint] { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + pub(crate) fn applied_member_constraints(&self, r: RegionVid) -> &[AppliedMemberConstraint] { + let scc = self.constraint_sccs.scc(r); binary_search_util::binary_search_slice( &self.member_constraints_applied, |applied| applied.member_region_scc, @@ -2234,7 +2231,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { r: RegionVid, body: &Body<'_>, ) -> Option { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); let locations = self.scc_values.locations_outlived_by(scc); for location in locations { let bb = &body[location.block]; From bbc400993eadea8a927cc5f96a15cc7c493c7a88 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:31:57 +1000 Subject: [PATCH 10/11] Remove `ToRegionVid`. It is only implemented for `Region`, where it is equivalent to the inherent `as_var` method. --- compiler/rustc_borrowck/src/borrow_set.rs | 5 ++-- .../src/constraint_generation.rs | 6 ++--- .../src/diagnostics/find_use.rs | 3 +-- .../src/diagnostics/region_name.rs | 10 ++++---- .../src/diagnostics/var_name.rs | 6 ++--- compiler/rustc_borrowck/src/nll.rs | 17 +------------- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/type_check/constraint_conversion.rs | 3 +-- .../src/type_check/liveness/mod.rs | 5 +--- compiler/rustc_borrowck/src/type_check/mod.rs | 7 +++--- .../rustc_borrowck/src/universal_regions.rs | 23 +++++++++---------- 11 files changed, 32 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index fa0552e012de1..4824f6346d4c8 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,6 +1,5 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use crate::nll::ToRegionVid; use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; use crate::BorrowIndex; @@ -204,7 +203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { return; } - let region = region.to_region_vid(); + let region = region.as_var(); let borrow = BorrowData { kind, @@ -279,7 +278,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { let borrow_data = &self.location_map[&location]; assert_eq!(borrow_data.reserve_location, location); assert_eq!(borrow_data.kind, kind); - assert_eq!(borrow_data.region, region.to_region_vid()); + assert_eq!(borrow_data.region, region.as_var()); assert_eq!(borrow_data.borrowed_place, place); } diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index 1427f5cb31d9c..2aa09a3f26c17 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -12,8 +12,8 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use crate::{ - borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid, - places_conflict, region_infer::values::LivenessValues, + borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict, + region_infer::values::LivenessValues, }; pub(super) fn generate_constraints<'tcx>( @@ -170,7 +170,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> { debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location); self.infcx.tcx.for_each_free_region(&live_ty, |live_region| { - let vid = live_region.to_region_vid(); + let vid = live_region.as_var(); self.liveness_constraints.add_element(vid, location); }); } diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index e2d04324f3b62..2495613fea1d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -6,7 +6,6 @@ use std::rc::Rc; use crate::{ def_use::{self, DefUse}, - nll::ToRegionVid, region_infer::{Cause, RegionInferenceContext}, }; use rustc_data_structures::fx::FxIndexSet; @@ -117,7 +116,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> { let mut found_it = false; self.tcx.for_each_free_region(&local_ty, |r| { - if r.to_region_vid() == self.region_vid { + if r.as_var() == self.region_vid { found_it = true; } }); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cc5a1f5ab122d..f69c4829ae299 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; +use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. @@ -497,7 +497,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // & // - let's call the lifetime of this reference `'1` (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => { - if region.to_region_vid() == needle_fr { + if region.as_var() == needle_fr { // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); let ampersand_span = source_map.start_point(hir_ty.span); @@ -598,7 +598,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { for (kind, hir_arg) in iter::zip(substs, args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { - if r.to_region_vid() == needle_fr { + if r.as_var() == needle_fr { return Some(lt); } } @@ -666,7 +666,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); - if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { + if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) { return None; } @@ -803,7 +803,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let tcx = self.infcx.tcx; - if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) { + if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) { return None; } diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 80b2787ce0c42..376415e3d3208 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,8 +1,8 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +use crate::region_infer::RegionInferenceContext; use crate::Upvar; -use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; use rustc_index::vec::{Idx, IndexSlice}; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; @@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { - let r = r.to_region_vid(); + let r = r.as_var(); debug!("get_upvar_index_for_region: r={r:?} fr={fr:?}"); r == fr }) @@ -96,7 +96,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( |arg_ty| { debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}"); - tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) + tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr) }, )?; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 8b5ff999e9b3d..59a3ab3189d75 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_span::symbol::sym; use std::env; use std::io; @@ -444,21 +444,6 @@ fn for_each_region_constraint<'tcx>( Ok(()) } -/// Right now, we piggy back on the `ReVar` to store our NLL inference -/// regions. These are indexed with `RegionVid`. This method will -/// assert that the region is a `ReVar` and extract its internal index. -/// This is reasonable because in our MIR we replace all universal regions -/// with inference variables. -pub trait ToRegionVid { - fn to_region_vid(self) -> RegionVid; -} - -impl<'tcx> ToRegionVid for Region<'tcx> { - fn to_region_vid(self) -> RegionVid { - if let ty::ReVar(vid) = *self { vid } else { bug!("region is not an ReVar: {:?}", self) } - } -} - pub(crate) trait ConstraintDescription { fn description(&self) -> &'static str; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index ce6f3690e1904..729f3dbff3b46 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1130,7 +1130,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let r_vid = self.to_region_vid(r); let r_scc = self.constraint_sccs.scc(r_vid); - // The challenge if this. We have some region variable `r` + // The challenge is this. We have some region variable `r` // whose value is a set of CFG points and universal // regions. We want to find if that set is *equivalent* to // any of the named regions found in the closure. diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index a93561350062c..71eae7b27d1db 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -12,7 +12,6 @@ use rustc_span::{Span, DUMMY_SP}; use crate::{ constraints::OutlivesConstraint, - nll::ToRegionVid, region_infer::TypeTest, type_check::{Locations, MirTypeckRegionConstraints}, universal_regions::UniversalRegions, @@ -198,7 +197,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { if let ty::RePlaceholder(placeholder) = *r { - self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid() + self.constraints.placeholder_region(self.infcx, placeholder).as_var() } else { self.universal_regions.to_region_vid(r) } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index a411aec518e93..f1ad0ca55ccfd 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -11,7 +11,6 @@ use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, - nll::ToRegionVid, region_infer::values::RegionValueElements, universal_regions::UniversalRegions, }; @@ -80,9 +79,7 @@ fn compute_relevant_live_locals<'tcx>( ) -> (Vec, Vec) { let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) = body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| { - if tcx.all_free_regions_meet(&local_decl.ty, |r| { - free_regions.contains(&r.to_region_vid()) - }) { + if tcx.all_free_regions_meet(&local_decl.ty, |r| free_regions.contains(&r.as_var())) { Either::Left(local) } else { Either::Right(local) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6d8305b7d471b..375eca1b29d3d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -56,7 +56,6 @@ use crate::{ facts::AllFacts, location::LocationTable, member_constraints::MemberConstraintSet, - nll::ToRegionVid, path_utils, region_infer::values::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, @@ -2419,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(all_facts) = all_facts { let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); if let Some(borrow_index) = borrow_set.get_index_of(&location) { - let region_vid = borrow_region.to_region_vid(); + let region_vid = borrow_region.as_var(); all_facts.loan_issued_at.push(( region_vid, borrow_index, @@ -2465,8 +2464,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match base_ty.kind() { ty::Ref(ref_region, _, mutbl) => { constraints.outlives_constraints.push(OutlivesConstraint { - sup: ref_region.to_region_vid(), - sub: borrow_region.to_region_vid(), + sup: ref_region.as_var(), + sub: borrow_region.as_var(), locations: location.to_locations(), span: location.to_locations().span(body), category, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 35dfc1f7d129a..70fddb1057c09 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -28,7 +28,6 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::Symbol; use std::iter; -use crate::nll::ToRegionVid; use crate::renumber::{BoundRegionInfo, RegionCtxt}; use crate::BorrowckInferCtxt; @@ -406,7 +405,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // Create the "global" region that is always free in all contexts: 'static. let fr_static = - self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).to_region_vid(); + self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).as_var(); // We've now added all the global regions. The next ones we // add will be external. @@ -446,7 +445,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }, ); @@ -480,7 +479,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); @@ -499,7 +498,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let reg_vid = self .infcx .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic"))) - .to_region_vid(); + .as_var(); let region = self.infcx.tcx.mk_re_var(reg_vid); let va_list_ty = @@ -514,7 +513,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let fr_fn_body = self .infcx .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body"))) - .to_region_vid(); + .as_var(); let num_universals = self.infcx.num_region_vars(); @@ -635,7 +634,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid())); + iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } } @@ -789,7 +788,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name))) }; - indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); + indices.insert_late_bound_region(liberated_region, region_vid.as_var()); debug!(?liberated_region, ?region_vid); region_vid }); @@ -822,7 +821,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); } @@ -843,7 +842,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { }) }; - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); } @@ -861,7 +860,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { } /// Converts `r` into a local inference variable: `r` can either - /// by a `ReVar` (i.e., already a reference to an inference + /// be a `ReVar` (i.e., already a reference to an inference /// variable) or it can be `'static` or some early-bound /// region. This is useful when taking the results from /// type-checking and trait-matching, which may sometimes @@ -870,7 +869,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// fully initialized. pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { if let ty::ReVar(..) = *r { - r.to_region_vid() + r.as_var() } else if r.is_error() { // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if From 72605cd267fa0a812e74ad8412738b4db37aca9d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 16:49:13 +1000 Subject: [PATCH 11/11] Remove some unused type folders. I'm surprised the compiler doesn't warn about these. It appears having an `impl` on a struct is enough to avoid a warning about it never being constructed. --- .../rustc_hir_analysis/src/collect/type_of.rs | 27 +------ compiler/rustc_hir_typeck/src/op.rs | 22 +----- compiler/rustc_middle/src/ty/sty.rs | 79 +------------------ .../src/traits/auto_trait.rs | 21 ----- 4 files changed, 4 insertions(+), 145 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 225b155058076..c173bd913a84c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -8,10 +8,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{ - self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, -}; +use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -874,28 +871,6 @@ fn infer_placeholder_type<'a>( item_ident: Ident, kind: &'static str, ) -> Ty<'a> { - // Attempts to make the type nameable by turning FnDefs into FnPtrs. - struct MakeNameable<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> TypeFolder> for MakeNameable<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = match *ty.kind() { - ty::FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) - } - _ => ty, - }; - - ty.super_fold_with(self) - } - } - let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 0ab6af127c096..a52c94cb00c53 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -12,9 +12,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{ - self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt, -}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; @@ -965,21 +963,3 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } } - -struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span); - -impl<'tcx> TypeFolder> for TypeParamEraser<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.0.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.kind() { - ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: self.1, - }), - _ => ty.super_fold_with(self), - } - } -} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index bbf6430a5ae70..96c1577d52bcb 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; @@ -1156,81 +1156,6 @@ where } } -struct SkipBindersAt<'tcx> { - tcx: TyCtxt<'tcx>, - index: ty::DebruijnIndex, -} - -impl<'tcx> FallibleTypeFolder> for SkipBindersAt<'tcx> { - type Error = (); - - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> - where - T: ty::TypeFoldable>, - { - self.index.shift_in(1); - let value = t.try_map_bound(|t| t.try_fold_with(self)); - self.index.shift_out(1); - value - } - - fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { - if !ty.has_escaping_bound_vars() { - Ok(ty) - } else if let ty::Bound(index, bv) = *ty.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_bound(index.shifted_out(1), bv)) - } - } else { - ty.try_super_fold_with(self) - } - } - - fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { - if !r.has_escaping_bound_vars() { - Ok(r) - } else if let ty::ReLateBound(index, bv) = r.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv)) - } - } else { - r.try_super_fold_with(self) - } - } - - fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { - if !ct.has_escaping_bound_vars() { - Ok(ct) - } else if let ty::ConstKind::Bound(index, bv) = ct.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_const( - ty::ConstKind::Bound(index.shifted_out(1), bv), - ct.ty().try_fold_with(self)?, - )) - } - } else { - ct.try_super_fold_with(self) - } - } - - fn try_fold_predicate( - &mut self, - p: ty::Predicate<'tcx>, - ) -> Result, Self::Error> { - if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) } - } -} - /// Represents the projection of an associated type. /// /// For a projection, this would be `>::N`. diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a53d414be9e7a..686631e5369fb 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -9,7 +9,6 @@ use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ImplPolarity, Region, RegionVid}; @@ -851,23 +850,3 @@ impl<'tcx> AutoTraitFinder<'tcx> { infcx.freshen(p) } } - -/// Replaces all ReVars in a type with ty::Region's, using the provided map -pub struct RegionReplacer<'a, 'tcx> { - vid_to_region: &'a FxHashMap>, - tcx: TyCtxt<'tcx>, -} - -impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - (match *r { - ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), - _ => None, - }) - .unwrap_or_else(|| r.super_fold_with(self)) - } -}