From e11a6a9cacdae64f1ee6fd412af273931d3ef25a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Dec 2023 00:42:58 +0000 Subject: [PATCH 1/5] No need to pass region bound pairs to resolve_regions_with_wf_tys --- .../rustc_hir_analysis/src/check/wfcheck.rs | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0978a5e65969a..0895cb5e771ce 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -10,10 +10,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; -use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; -use rustc_infer::infer::outlives::obligations::TypeOutlives; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -731,10 +729,12 @@ fn ty_known_to_outlive<'tcx>( ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |infcx, region_bound_pairs| { - let origin = infer::RelateParamBound(DUMMY_SP, ty, None); - let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.register_region_obligation(infer::RegionObligation { + sub_region: region, + sup_type: ty, + origin: infer::RelateParamBound(DUMMY_SP, ty, None), + }); }) } @@ -748,40 +748,32 @@ fn region_known_to_outlive<'tcx>( region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |mut infcx, _| { - use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; - let origin = infer::RelateRegionParamBound(DUMMY_SP); - // `region_a: region_b` -> `region_b <= region_a` - infcx.push_sub_region_constraint( - origin, - region_b, - region_a, - ConstraintCategory::BoringNoLocation, - ); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a); }) } /// Given a known `param_env` and a set of well formed types, set up an /// `InferCtxt`, call the passed function (to e.g. set up region constraints /// to be tested), then resolve region and return errors -fn resolve_regions_with_wf_tys<'tcx>( +fn test_region_obligations<'tcx>( tcx: TyCtxt<'tcx>, id: LocalDefId, param_env: ty::ParamEnv<'tcx>, wf_tys: &FxIndexSet>, - add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>), + add_constraints: impl FnOnce(&InferCtxt<'tcx>), ) -> bool { // Unfortunately, we have to use a new `InferCtxt` each call, because // region constraints get added and solved there and we need to test each // call individually. let infcx = tcx.infer_ctxt().build(); + + add_constraints(&infcx); + let outlives_environment = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, id, wf_tys), ); - let region_bound_pairs = outlives_environment.region_bound_pairs(); - - add_constraints(&infcx, region_bound_pairs); let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); From 028d29301f9cbd174f3e21652d1c20d58af132ce Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 22:45:34 +0000 Subject: [PATCH 2/5] Deeply normalize when processing registered region obligations --- .../src/check/compare_impl_item.rs | 1 + .../src/check/compare_impl_item/refine.rs | 1 + .../rustc_hir_analysis/src/check/dropck.rs | 2 + .../rustc_hir_analysis/src/check/wfcheck.rs | 1 + .../src/infer/error_reporting/mod.rs | 11 +++++- .../src/infer/lexical_region_resolve/mod.rs | 5 ++- .../rustc_infer/src/infer/outlives/mod.rs | 16 ++++++-- .../src/infer/outlives/obligations.rs | 12 ++++-- compiler/rustc_trait_selection/src/lib.rs | 1 + compiler/rustc_trait_selection/src/regions.rs | 37 +++++++++++++++++++ .../src/traits/auto_trait.rs | 2 +- .../src/traits/coherence.rs | 1 + .../src/traits/engine.rs | 1 + .../rustc_trait_selection/src/traits/misc.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 1 + .../next-solver/specialization-transmute.rs | 1 + .../specialization-transmute.stderr | 8 ++-- 17 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/regions.rs 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 479421af77fef..379c1154e5f26 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericParamDefKind, TyCtxt}; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{ diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 6d2ebb150b957..3d3b21eabb383 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 9fe95487bb9e0..3d2d667763a4c 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -8,6 +8,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, TyCtxt}; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::errors; @@ -188,6 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) } + RegionResolutionError::CannotNormalize(..) => todo!(), }; guar = Some( struct_span_code_err!( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0895cb5e771ce..b9c9eec28139a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,6 +24,7 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e19177fccefd8..0630bb2f44bb3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -518,6 +518,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } + + RegionResolutionError::CannotNormalize(ty, origin) => { + self.tcx + .dcx() + .struct_span_err(origin.span(), format!("cannot normalize `{ty}`")) + .emit(); + } } } } @@ -559,7 +566,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::ConcreteFailure(..) | RegionResolutionError::SubSupConflict(..) - | RegionResolutionError::UpperBoundUniverseConflict(..) => false, + | RegionResolutionError::UpperBoundUniverseConflict(..) + | RegionResolutionError::CannotNormalize(..) => false, }; let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { @@ -574,6 +582,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), + RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(), }); errors } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 0562c6ccfcf75..4a1169e68e087 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> { SubregionOrigin<'tcx>, // cause of the constraint Region<'tcx>, // the placeholder `'b` ), + + CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>), } impl<'tcx> RegionResolutionError<'tcx> { @@ -106,7 +108,8 @@ impl<'tcx> RegionResolutionError<'tcx> { RegionResolutionError::ConcreteFailure(origin, _, _) | RegionResolutionError::GenericBoundFailure(origin, _, _) | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _) - | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin, + | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) + | RegionResolutionError::CannotNormalize(_, origin) => origin, } } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 6379f84aa252f..97ab2f32c40ad 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -5,7 +5,7 @@ use super::{InferCtxt, RegionResolutionError}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty; +use rustc_middle::ty::{self, Ty}; pub mod components; pub mod env; @@ -41,12 +41,22 @@ 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`. + /// + /// If you are in a crate that has access to `rustc_trai_selection`, + /// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`, + /// which knows how to normalize registered region obligations. #[must_use] - pub fn resolve_regions( + pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, + deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result, Ty<'tcx>>, ) -> Vec> { - self.process_registered_region_obligations(outlives_env); + match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { + Ok(()) => {} + Err((ty, origin)) => { + return vec![RegionResolutionError::CannotNormalize(ty, origin)]; + } + }; let (var_infos, data) = { let mut inner = self.inner.borrow_mut(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index d7a3bfcbc41b6..1621e323d2cae 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -123,15 +123,19 @@ impl<'tcx> InferCtxt<'tcx> { /// flow of the inferencer. The key point is that it is /// invoked after all type-inference variables have been bound -- /// right before lexical region resolution. - #[instrument(level = "debug", skip(self, outlives_env))] - pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))] + pub fn process_registered_region_obligations( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result, E>, + ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?; debug!(?sup_type, ?sub_region, ?origin); - let sup_type = self.resolve_vars_if_possible(sup_type); let outlives = &mut TypeOutlives::new( self, @@ -143,6 +147,8 @@ impl<'tcx> InferCtxt<'tcx> { let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); } + + Ok(()) } } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 995ed1e3b573b..5ec45212bc791 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -39,6 +39,7 @@ extern crate smallvec; pub mod errors; pub mod infer; +pub mod regions; pub mod solve; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs new file mode 100644 index 0000000000000..3c53da32d0a1b --- /dev/null +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -0,0 +1,37 @@ +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_middle::traits::ObligationCause; + +pub trait InferCtxtRegionExt<'tcx> { + /// Resolve regions, using the deep normalizer to normalize any type-outlives + /// obligations in the process. This is in `rustc_trait_selection` because + /// we need to normalize. + /// + /// Prefer this method over `resolve_regions_with_normalize`, unless you are + /// doing something specific for normalization. + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec>; +} + +impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.resolve_regions(outlives_env, |ty| { + let ty = self.resolve_vars_if_possible(ty); + + if self.next_trait_solver() { + crate::solve::deeply_normalize( + self.at(&ObligationCause::dummy(), outlives_env.param_env), + ty, + ) + .map_err(|_| ty) + } else { + Ok(ty) + } + }) + } +} diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c43447585746a..87b68a8bd2d68 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - infcx.process_registered_region_obligations(&outlives_env); + let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty| Ok(ty)); 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 ecbb92ca5b996..c49185a52c7ef 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,6 +6,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; +use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::engine::TraitEngineExt; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 013a50f9fa1c8..caf950037fdfd 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use super::FulfillmentContext; use super::TraitEngine; +use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 0cd376fcbbdc8..93f9c2333f0c0 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,5 +1,6 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. +use crate::regions::InferCtxtRegionExt; use crate::traits::{self, ObligationCause, ObligationCtxt}; use hir::LangItem; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 080ad7bd549c8..a7f6021d57a96 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -25,6 +25,7 @@ pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, TyCtxtInferExt}; +use crate::regions::InferCtxtRegionExt; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_errors::ErrorGuaranteed; diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index ff25656a7ff59..e7de564877d09 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,4 +1,5 @@ // compile-flags: -Znext-solver +//~^ ERROR cannot normalize `::Id` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index a5459165587ca..a1cf5b761e34f 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-transmute.rs:3:12 + --> $DIR/specialization-transmute.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,12 +8,14 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default +error: cannot normalize `::Id` + error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:13:23 + --> $DIR/specialization-transmute.rs:14:23 | LL | default type Id = T; | ^ cannot infer type for associated type `::Id` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0282`. From fef38a6337c6acf14eb70bf013717f484aa57eec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 25 Dec 2023 21:37:29 +0000 Subject: [PATCH 3/5] Normalize caller bounds --- .../src/type_check/constraint_conversion.rs | 3 +- .../src/infer/outlives/obligations.rs | 28 ++++++++++++++++--- .../rustc_infer/src/infer/outlives/verify.rs | 10 +++---- compiler/rustc_infer/src/lib.rs | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 21d8026e17089..02ef7357d6645 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -157,7 +157,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, Some(implicit_region_bound), - param_env, + // FIXME(-Znext-solver): These bounds are not normalized! + param_env.caller_bounds(), ) .type_must_outlive(origin, t1, r2, constraint_category); } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1621e323d2cae..bc66522a8b6c7 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,9 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{GenericArgKind, ToPredicate}; +use rustc_span::DUMMY_SP; use smallvec::smallvec; use super::env::OutlivesEnvironment; @@ -131,6 +132,25 @@ impl<'tcx> InferCtxt<'tcx> { ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); + let normalized_caller_bounds: Vec<_> = outlives_env + .param_env + .caller_bounds() + .iter() + .filter_map(|clause| { + let bound_clause = clause.kind(); + let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { + return None; + }; + Some(deeply_normalize_ty(outlives.0).map(|ty| { + bound_clause + .rebind(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives.1))) + .to_predicate(self.tcx) + })) + }) + // FIXME: How do we accurately report an error here :( + .try_collect() + .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; + let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { @@ -142,7 +162,7 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx, outlives_env.region_bound_pairs(), None, - outlives_env.param_env, + &normalized_caller_bounds, ); let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); @@ -196,7 +216,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { Self { delegate, @@ -205,7 +225,7 @@ where tcx, region_bound_pairs, implicit_region_bound, - param_env, + caller_bounds, ), } } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7a85268492b43..2ad8b6b98e3e8 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { /// Outside of borrowck the only way to prove `T: '?0` is by /// setting `'?0` to `'empty`. implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,9 +31,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { - Self { tcx, region_bound_pairs, implicit_region_bound, param_env } + Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } #[instrument(level = "debug", skip(self))] @@ -219,8 +219,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); + let param_bounds = + self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 9e3de1825ed37..e2dd4b49e1a4b 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -21,6 +21,7 @@ #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] +#![feature(iterator_try_collect)] #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc From dc050f6d5bb1cb9d7529b6d9881ad99d8ce6a20d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Jan 2024 19:33:45 +0000 Subject: [PATCH 4/5] Add a test --- .../normalize-region-obligations.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/traits/next-solver/normalize-region-obligations.rs diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize-region-obligations.rs new file mode 100644 index 0000000000000..13c86b630f60e --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-region-obligations.rs @@ -0,0 +1,22 @@ +// revisions: normalize_param_env normalize_obligation +// check-pass +// compile-flags: -Znext-solver + +trait Foo { + #[cfg(normalize_param_env)] + type Gat<'a> where ::Assoc: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> where Self: 'a; +} + +trait Mirror { type Assoc: ?Sized; } +impl Mirror for T { type Assoc = T; } + +impl Foo for T { + #[cfg(normalize_param_env)] + type Gat<'a> = i32 where T: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> = i32 where ::Assoc: 'a; +} + +fn main() {} From 720d7a7a03b9997644fe28a12a80a910b2652760 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 19:18:14 +0000 Subject: [PATCH 5/5] Apply suggestions from review --- .../src/type_check/constraint_conversion.rs | 15 ++++++----- .../src/type_check/free_region_relations.rs | 10 +++++-- compiler/rustc_borrowck/src/type_check/mod.rs | 13 +++++++-- .../rustc_hir_analysis/src/check/dropck.rs | 2 +- .../rustc_infer/src/infer/outlives/mod.rs | 8 +++--- .../src/infer/outlives/obligations.rs | 23 +++++++++------- .../rustc_infer/src/infer/outlives/verify.rs | 27 ++++--------------- compiler/rustc_trait_selection/src/regions.rs | 7 +++-- .../src/traits/auto_trait.rs | 2 +- .../next-solver/unsound-region-obligation.rs | 13 +++++++++ .../unsound-region-obligation.stderr | 7 +++++ 11 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 tests/ui/traits/next-solver/unsound-region-obligation.rs create mode 100644 tests/ui/traits/next-solver/unsound-region-obligation.stderr diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 02ef7357d6645..52559f9039b65 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -33,7 +33,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { /// our special inference variable there, we would mess that up. region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, - param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -47,7 +47,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, - param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -59,7 +59,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions, region_bound_pairs, implicit_region_bound, - param_env, + known_type_outlives_obligations, locations, span, category, @@ -136,7 +136,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Extract out various useful fields we'll need below. let ConstraintConversion { - tcx, region_bound_pairs, implicit_region_bound, param_env, .. + tcx, + region_bound_pairs, + implicit_region_bound, + known_type_outlives_obligations, + .. } = *self; let ty::OutlivesPredicate(k1, r2) = predicate; @@ -157,8 +161,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, Some(implicit_region_bound), - // FIXME(-Znext-solver): These bounds are not normalized! - param_env.caller_bounds(), + known_type_outlives_obligations, ) .type_must_outlive(origin, t1, r2, constraint_category); } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 011b5b760c23a..d518f54fd2533 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -45,12 +45,14 @@ type NormalizedInputsAndOutput<'tcx> = Vec>; pub(crate) struct CreateResult<'tcx> { pub(crate) universal_region_relations: Frozen>, pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>, + pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } pub(crate) fn create<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, universal_regions: &Rc>, constraints: &mut MirTypeckRegionConstraints<'tcx>, @@ -58,6 +60,7 @@ pub(crate) fn create<'tcx>( UniversalRegionRelationsBuilder { infcx, param_env, + known_type_outlives_obligations, implicit_region_bound, constraints, universal_regions: universal_regions.clone(), @@ -175,6 +178,7 @@ impl UniversalRegionRelations<'_> { struct UniversalRegionRelationsBuilder<'this, 'tcx> { infcx: &'this InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], universal_regions: Rc>, implicit_region_bound: ty::Region<'tcx>, constraints: &'this mut MirTypeckRegionConstraints<'tcx>, @@ -200,7 +204,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local(); let span = tcx.def_span(defining_ty_def_id); - // Insert the facts we know from the predicates. Why? Why not. + // Insert the `'a: 'b` we know from the predicates. + // This does not consider the type-outlives. let param_env = self.param_env; self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env)); @@ -308,6 +313,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), + known_type_outlives_obligations: self.known_type_outlives_obligations, region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } @@ -322,7 +328,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { &self.universal_regions, &self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, Locations::All(span), span, ConstraintCategory::Internal, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 488dfc64cf6f0..59c4d9a6c78ca 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -152,9 +152,14 @@ pub(crate) fn type_check<'mir, 'tcx>( universal_region_relations, region_bound_pairs, normalized_inputs_and_output, + known_type_outlives_obligations, } = free_region_relations::create( infcx, param_env, + // FIXME(-Znext-solver): These are unnormalized. Normalize them. + infcx.tcx.arena.alloc_from_iter( + param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()), + ), implicit_region_bound, universal_regions, &mut constraints, @@ -176,6 +181,7 @@ pub(crate) fn type_check<'mir, 'tcx>( body, param_env, ®ion_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, &mut borrowck_context, ); @@ -850,6 +856,7 @@ struct TypeChecker<'a, 'tcx> { /// all of the promoted items. user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -1000,6 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body: &'a Body<'tcx>, param_env: ty::ParamEnv<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, ) -> Self { @@ -1010,6 +1018,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_type_annotations: &body.user_type_annotations, param_env, region_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, borrowck_context, reported_errors: Default::default(), @@ -1127,7 +1136,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, locations, locations.span(self.body), category, @@ -2731,7 +2740,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, locations, DUMMY_SP, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 3d2d667763a4c..7b60457affa82 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -189,7 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) } - RegionResolutionError::CannotNormalize(..) => todo!(), + RegionResolutionError::CannotNormalize(..) => unreachable!(), }; guar = Some( struct_span_code_err!( diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 97ab2f32c40ad..926e198b21915 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,7 +1,7 @@ //! Various code related to computing outlives relations. use self::env::OutlivesEnvironment; use super::region_constraints::RegionConstraintData; -use super::{InferCtxt, RegionResolutionError}; +use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; use rustc_middle::traits::query::OutlivesBound; @@ -42,14 +42,14 @@ impl<'tcx> InferCtxt<'tcx> { /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. /// - /// If you are in a crate that has access to `rustc_trai_selection`, - /// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`, + /// If you are in a crate that has access to `rustc_trait_selection`, + /// then it's probably better to use `resolve_regions`, /// which knows how to normalize registered region obligations. #[must_use] pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, - deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result, Ty<'tcx>>, + deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, Ty<'tcx>>, ) -> Vec> { match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { Ok(()) => {} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index bc66522a8b6c7..b10bf98e8b50a 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,8 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; +use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{GenericArgKind, ToPredicate}; use rustc_span::DUMMY_SP; use smallvec::smallvec; @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn process_registered_region_obligations( &self, outlives_env: &OutlivesEnvironment<'tcx>, - mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result, E>, + mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, E>, ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); @@ -141,20 +141,23 @@ impl<'tcx> InferCtxt<'tcx> { let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { return None; }; - Some(deeply_normalize_ty(outlives.0).map(|ty| { - bound_clause - .rebind(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives.1))) - .to_predicate(self.tcx) - })) + Some( + deeply_normalize_ty( + outlives.0, + SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP), + ) + .map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))), + ) }) - // FIXME: How do we accurately report an error here :( + // FIXME(-Znext-solver): How do we accurately report an error here :( .try_collect() .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?; + let sup_type = + deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?; debug!(?sup_type, ?sub_region, ?origin); let outlives = &mut TypeOutlives::new( @@ -216,7 +219,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { Self { delegate, diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 2ad8b6b98e3e8..5d2f51c689b95 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { /// Outside of borrowck the only way to prove `T: '?0` is by /// setting `'?0` to `'empty`. implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,7 +31,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } @@ -219,8 +219,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let param_bounds = - self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied()); + let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| { + super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) + }); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -307,22 +308,4 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { .filter_map(|p| p.no_bound_vars()) .map(|OutlivesPredicate(_, r)| r) } - - /// Searches through a predicate list for a predicate `T: 'a`. - /// - /// Careful: does not elaborate predicates, and just uses `==` - /// when comparing `ty` for equality, so `ty` must be something - /// that does not involve inference variables and where you - /// otherwise want a precise match. - fn collect_outlives_from_clause_list( - &self, - erased_ty: Ty<'tcx>, - clauses: impl Iterator>, - ) -> impl Iterator, ty::Region<'tcx>>>> - { - let tcx = self.tcx; - clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { - super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) - }) - } } diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 3c53da32d0a1b..e8929f114e165 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -20,12 +20,15 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec> { - self.resolve_regions(outlives_env, |ty| { + self.resolve_regions_with_normalize(outlives_env, |ty, origin| { let ty = self.resolve_vars_if_possible(ty); if self.next_trait_solver() { crate::solve::deeply_normalize( - self.at(&ObligationCause::dummy(), outlives_env.param_env), + self.at( + &ObligationCause::dummy_with_span(origin.span()), + outlives_env.param_env, + ), ty, ) .map_err(|_| ty) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 87b68a8bd2d68..b258007787de9 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty| Ok(ty)); + let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs new file mode 100644 index 0000000000000..b8bfa03538887 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs @@ -0,0 +1,13 @@ +//~ ERROR the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime +// compile-flags: -Znext-solver +// Regression test for rust-lang/trait-system-refactor-initiative#59 + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr new file mode 100644 index 0000000000000..518de7ea3e025 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr @@ -0,0 +1,7 @@ +error[E0477]: the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime + | + = note: type must satisfy the static lifetime + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0477`.