From 1694ea187392a4832a5d69fa008b1e5ff13fe584 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Jul 2022 05:27:45 +0000 Subject: [PATCH 1/2] use check_region_obligations_and_report_errors in more places to avoid ICEs --- compiler/rustc_typeck/src/check/compare_method.rs | 6 ++++-- compiler/rustc_typeck/src/coherence/builtin.rs | 4 ++-- .../src/impl_wf_check/min_specialization.rs | 3 +-- src/test/ui/coercion/issue-53475.rs | 13 +++++++++++++ src/test/ui/coercion/issue-53475.stderr | 14 ++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/coercion/issue-53475.rs create mode 100644 src/test/ui/coercion/issue-53475.stderr diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index af77efc3c2d57..e3ac23686b6d6 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1154,8 +1154,10 @@ pub(crate) fn compare_const_impl<'tcx>( } let outlives_environment = OutlivesEnvironment::new(param_env); - infcx - .resolve_regions_and_report_errors(impl_c.def_id.expect_local(), &outlives_environment); + infcx.check_region_obligations_and_report_errors( + impl_c.def_id.expect_local(), + &outlives_environment, + ); }); } diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index d8e42729ff31d..1e404fda035af 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -349,7 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did, &outlives_env); + infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -606,7 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did, &outlives_env); + infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } }) diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index f16888345e9d5..74abb71a18e76 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -158,8 +158,7 @@ fn get_impl_substs<'tcx>( implied_bounds, tcx.hir().local_def_id_to_hir_id(impl1_def_id), ); - infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); + infcx.check_region_obligations_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/src/test/ui/coercion/issue-53475.rs b/src/test/ui/coercion/issue-53475.rs new file mode 100644 index 0000000000000..3770c024fb92e --- /dev/null +++ b/src/test/ui/coercion/issue-53475.rs @@ -0,0 +1,13 @@ +#![feature(coerce_unsized)] + +use std::any::Any; +use std::ops::CoerceUnsized; + +struct Foo { + data: Box, +} + +impl CoerceUnsized> for Foo {} +//~^ ERROR the parameter type `T` may not live long enough + +fn main() {} diff --git a/src/test/ui/coercion/issue-53475.stderr b/src/test/ui/coercion/issue-53475.stderr new file mode 100644 index 0000000000000..522c50dca9508 --- /dev/null +++ b/src/test/ui/coercion/issue-53475.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-53475.rs:10:1 + | +LL | impl CoerceUnsized> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | impl CoerceUnsized> for Foo {} + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. From 16f49800db7be11e7255036f05ca811c1bf98926 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 29 Jul 2022 06:17:17 +0000 Subject: [PATCH 2/2] Document check_region_obligations_and_report_errors, simplify a call to resolve_regions --- compiler/rustc_infer/src/infer/mod.rs | 4 ++++ compiler/rustc_infer/src/infer/outlives/obligations.rs | 6 ++++++ compiler/rustc_trait_selection/src/traits/coherence.rs | 8 +------- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0ac6e8c541b55..620e3358d2b97 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1324,6 +1324,10 @@ impl<'a, 'tcx> InferCtxt<'a, '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`. + /// + /// Make sure to call [`InferCtxt::process_registered_region_obligations`] + /// first, or preferrably use [`InferCtxt::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, diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a57971bfb697d..ad052f58ca854 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -111,6 +111,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } + /// NOTE: Prefer using [`InferCtxt::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 @@ -162,6 +165,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, '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, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index fa94aa19abda5..f62ccb99df5eb 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -398,13 +398,7 @@ fn resolve_negative_obligation<'cx, 'tcx>( let outlives_env = OutlivesEnvironment::new(param_env); infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - let errors = infcx.resolve_regions(&outlives_env); - - if !errors.is_empty() { - return false; - } - - true + infcx.resolve_regions(&outlives_env).is_empty() } pub fn trait_ref_is_knowable<'tcx>(