From 336660b62795a0f7f5a62bde02915414fe6c72b4 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 3 Apr 2023 15:55:13 +0300 Subject: [PATCH 1/3] implement implied_outlives_bounds_v2 query --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_middle/src/query/erase.rs | 4 + compiler/rustc_middle/src/query/mod.rs | 6 + compiler/rustc_middle/src/traits/query.rs | 2 +- .../src/solve/eval_ctxt.rs | 9 +- .../src/traits/outlives_bounds.rs | 32 +++- .../rustc_trait_selection/src/traits/wf.rs | 17 +- .../src/implied_outlives_bounds.rs | 150 ++++++++++++++---- .../normalization-nested.lifetime.stderr | 20 +-- .../ui/implied-bounds/normalization-nested.rs | 8 +- ...lization-preserve-equality.borrowck.stderr | 28 ++++ .../normalization-preserve-equality.rs | 26 +++ 12 files changed, 242 insertions(+), 62 deletions(-) create mode 100644 tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr create mode 100644 tests/ui/implied-bounds/normalization-preserve-equality.rs diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 862f0a9b0e2c6..f36a473aaaf3b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -106,7 +106,6 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( f(&mut wfcx); let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id); - let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); let errors = wfcx.select_all_or_error(); if !errors.is_empty() { @@ -114,6 +113,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( return; } + let implied_bounds = infcx.implied_bounds_tys_v2(param_env, body_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env); diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 7d9aea022898d..35dd2b59d4f08 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -59,6 +59,10 @@ impl EraseType for Result<&'_ T, traits::query::NoSolution> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], traits::query::NoSolution> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index be2657d25a694..786c4a32b8117 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1837,6 +1837,12 @@ rustc_queries! { desc { "computing implied outlives bounds for `{}`", goal.value.value } } + query implied_outlives_bounds_v2( + goal: ParamEnvAnd<'tcx, Ty<'tcx>> + ) -> Result<&'tcx [OutlivesBound<'tcx>], NoSolution> { + desc { "computing implied outlives bounds v2 for `{}`", goal.value } + } + /// Do not call this query directly: /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. query dropck_outlives( diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index c4f8718754f5f..910b085abbc96 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -209,7 +209,7 @@ pub struct NormalizationResult<'tcx> { /// case they are called implied bounds). They are fed to the /// `OutlivesEnv` which in turn is supplied to the region checker and /// other parts of the inference system. -#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift, HashStable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, HashStable)] pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 63a73f8d50d93..40cdb00e4bd6d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -658,8 +658,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { param_env: ty::ParamEnv<'tcx>, arg: ty::GenericArg<'tcx>, ) -> Option>>> { - crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg) - .map(|obligations| obligations.into_iter().map(|obligation| obligation.into())) + debug_assert_eq!(arg, self.infcx.resolve_vars_if_possible(arg)); + // FIXME: useless `Option` in return type? + Some( + crate::traits::wf::unnormalized_obligations(self.tcx(), param_env, arg) + .into_iter() + .map(|obligation| obligation.into()), + ) } pub(super) fn is_transmutable( diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 0db8023289127..0db3c5ac5533f 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -3,13 +3,15 @@ use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::NoSolution; use crate::traits::{ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; +use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt}; -use rustc_span::def_id::LocalDefId; +use rustc_span::DUMMY_SP; pub use rustc_middle::traits::query::OutlivesBound; type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; +type BoundsV2<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { fn implied_outlives_bounds( &self, @@ -24,6 +26,13 @@ pub trait InferCtxtExt<'a, 'tcx> { body_id: LocalDefId, tys: FxIndexSet>, ) -> Bounds<'a, 'tcx>; + + fn implied_bounds_tys_v2( + &'a self, + param_env: ty::ParamEnv<'tcx>, + _body_id: LocalDefId, + tys: FxIndexSet>, + ) -> BoundsV2<'a, 'tcx>; } impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { @@ -123,4 +132,25 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { ) -> Bounds<'a, 'tcx> { tys.into_iter().flat_map(move |ty| self.implied_outlives_bounds(param_env, body_id, ty)) } + + fn implied_bounds_tys_v2( + &'a self, + param_env: ParamEnv<'tcx>, + _body_id: LocalDefId, + tys: FxIndexSet>, + ) -> BoundsV2<'a, 'tcx> { + tys.into_iter() + .flat_map(move |ty| { + let ty = self.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(self).fold_ty(ty); + if ty.has_infer() { + // Infer vars can appear only in invalid code. See #110161. + self.tcx.sess.delay_span_bug(DUMMY_SP, "infer vars in implied bounds"); + return &[] as &[OutlivesBound<'_>]; + } + + self.tcx.implied_outlives_bounds_v2(param_env.and(ty)).unwrap_or(&[]) + }) + .copied() + } } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 22710c7c059a9..6df8345063caa 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -77,21 +77,20 @@ pub fn obligations<'tcx>( /// Compute the predicates that are required for a type to be well-formed. /// -/// This is only intended to be used in the new solver, since it does not -/// take into account recursion depth or proper error-reporting spans. +/// This is only intended to be used in implied bounds computation and in +/// the new solver, since it does not take into account recursion depth or +/// proper error-reporting spans. pub fn unnormalized_obligations<'tcx>( - infcx: &InferCtxt<'tcx>, + tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, -) -> Option>> { +) -> Vec> { if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { - return Some(vec![]); + return vec![]; } - debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); - let mut wf = WfPredicates { - tcx: infcx.tcx, + tcx, param_env, body_id: CRATE_DEF_ID, span: DUMMY_SP, @@ -100,7 +99,7 @@ pub fn unnormalized_obligations<'tcx>( item: None, }; wf.compute(arg); - Some(wf.out) + wf.out } /// Returns the obligations that make this trait reference diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index f5bba14d2fb9c..3a2da82b5465d 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -2,31 +2,121 @@ //! Do not call this query directory. See //! [`rustc_trait_selection::traits::query::type_op::implied_outlives_bounds`]. -use rustc_infer::infer::canonical::{self, Canonical}; +use rustc_infer::infer::canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; use rustc_trait_selection::traits::wf; -use rustc_trait_selection::traits::ObligationCtxt; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use smallvec::{smallvec, SmallVec}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { implied_outlives_bounds, ..*p }; + *p = Providers { implied_outlives_bounds_v2, ..*p }; +} + +fn implied_outlives_bounds_v2<'tcx>( + tcx: TyCtxt<'tcx>, + goal: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, +) -> Fallible<&'tcx [OutlivesBound<'tcx>]> { + let (param_env, goal_ty) = goal.into_parts(); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let normalize_op = |ty| { + let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty); + if !ocx.select_all_or_error().is_empty() { + return Err(NoSolution); + } + let ty = ocx.infcx.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(&infcx).fold_ty(ty); + assert!(!ty.has_infer()); + Ok(ty) + }; + + compute_implied_outlives_bounds_v2(tcx, goal_ty, normalize_op) +} + +/// For the sake of completeness, we should be careful when dealing with inference artifacts: +/// - This function shouldn't access an InferCtxt. +/// - `ty` must be fully resolved. +/// - `normalize_op` must return a fully resolved type. +fn compute_implied_outlives_bounds_v2<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + normalize_op: impl Fn(Ty<'tcx>) -> Fallible>, +) -> Fallible<&'tcx [OutlivesBound<'tcx>]> { + // Sometimes when we ask what it takes for T: WF, we get back that + // U: WF is required; in that case, we push U onto this stack and + // process it next. Because the resulting predicates aren't always + // guaranteed to be a subset of the original type, so we need to store the + // WF args we've computed in a set. + let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default(); + let mut wf_args = vec![ty.into(), normalize_op(ty)?.into()]; + + let mut outlives_bounds: Vec> = vec![]; + + while let Some(arg) = wf_args.pop() { + if !checked_wf_args.insert(arg) { + continue; + } + + // From the full set of obligations, just filter down to the region relationships. + for obligation in wf::unnormalized_obligations(tcx, ty::ParamEnv::empty(), arg) { + assert!(!obligation.has_escaping_bound_vars()); + let Some(pred) = obligation.predicate.kind().no_bound_vars() else { + continue; + }; + match pred { + ty::PredicateKind::Clause(ty::Clause::Trait(..)) + // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound + // if we ever support that + | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::Clause(ty::Clause::Projection(..)) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::AliasRelate(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} + + // We need to search through *all* WellFormed predicates + ty::PredicateKind::WellFormed(arg) => wf_args.push(arg), + + // We need to register region relationships + ty::PredicateKind::Clause(ty::Clause::RegionOutlives( + ty::OutlivesPredicate(r_a, r_b), + )) => outlives_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)), + + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( + ty_a, + r_b, + ))) => { + let ty_a = normalize_op(ty_a)?; + let mut components = smallvec![]; + push_outlives_components(tcx, ty_a, &mut components); + outlives_bounds.extend(implied_bounds_from_components(r_b, components)) + } + } + } + } + + Ok(tcx.arena.alloc_slice(&outlives_bounds)) } fn implied_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalTyGoal<'tcx>, -) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, - NoSolution, -> { +) -> Fallible>>> { tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| { let (param_env, ty) = key.into_parts(); compute_implied_outlives_bounds(ocx, param_env, ty) @@ -149,7 +239,7 @@ fn compute_implied_outlives_bounds<'tcx>( let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); - implied_bounds_from_components(r_b, components) + implied_bounds_from_components(r_b, components).collect() } ty::GenericArgKind::Const(_) => unreachable!(), }) @@ -165,28 +255,24 @@ fn compute_implied_outlives_bounds<'tcx>( fn implied_bounds_from_components<'tcx>( sub_region: ty::Region<'tcx>, sup_components: SmallVec<[Component<'tcx>; 4]>, -) -> Vec> { - sup_components - .into_iter() - .filter_map(|component| { - match component { - Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)), - Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)), - Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)), - Component::EscapingAlias(_) => - // If the projection has escaping regions, don't - // try to infer any implied bounds even for its - // free components. This is conservative, because - // the caller will still have to prove that those - // free components outlive `sub_region`. But the - // idea is that the WAY that the caller proves - // that may change in the future and we want to - // give ourselves room to get smarter here. - { - None - } - Component::UnresolvedInferenceVariable(..) => None, - } - }) - .collect() +) -> impl Iterator> { + sup_components.into_iter().filter_map(move |component| { + match component { + Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)), + Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)), + Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)), + // If the projection has escaping regions, don't + // try to infer any implied bounds even for its + // free components. This is conservative, because + // the caller will still have to prove that those + // free components outlive `sub_region`. But the + // idea is that the WAY that the caller proves + // that may change in the future and we want to + // give ourselves room to get smarter here. + Component::EscapingAlias(_) => None, + // FIXME: We shouldn't have inference vars in implied bounds computation. + // Panic here once we remove the legacy implied bounds. + Component::UnresolvedInferenceVariable(..) => None, + } + }) } diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr index 898e5e9511e71..797bd8c1aa035 100644 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -1,18 +1,10 @@ -error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:35:20 +error: lifetime may not live long enough + --> $DIR/normalization-nested.rs:39:5 | -LL | pub fn test<'x>(_: Map>, s: &'x str) -> &'static str { - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here - | -note: `'static` lifetime requirement introduced by this bound - --> $DIR/normalization-nested.rs:33:14 - | -LL | I::Item: 'static; - | ^^^^^^^ +LL | pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { + | -- lifetime `'x` defined here +LL | s + | ^ returning this value requires that `'x` must outlive `'static` error: aborting due to previous error -For more information about this error, try `rustc --explain E0759`. diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs index 5f1cbb3f69779..6cfb8163a0e6e 100644 --- a/tests/ui/implied-bounds/normalization-nested.rs +++ b/tests/ui/implied-bounds/normalization-nested.rs @@ -5,7 +5,7 @@ // revisions: param_ty lifetime // [param_ty] check-pass // [lifetime] check-fail -// [lifetime] known-bug: #109799 +// [lifetime] issue: #109799 pub trait Iter { type Item; @@ -32,8 +32,12 @@ where I: Iter, I::Item: 'static; -pub fn test<'x>(_: Map>, s: &'x str) -> &'static str { +// passes for lifetime and type paramters. +pub fn test_wfcheck<'x>(_: Map>) {} + +pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { s + //[lifetime]~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr new file mode 100644 index 0000000000000..32ec131f0a810 --- /dev/null +++ b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/normalization-preserve-equality.rs:20:1 + | +LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { + | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here + | requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/normalization-preserve-equality.rs:20:1 + | +LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { + | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here + | requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.rs b/tests/ui/implied-bounds/normalization-preserve-equality.rs new file mode 100644 index 0000000000000..592f12a51469f --- /dev/null +++ b/tests/ui/implied-bounds/normalization-preserve-equality.rs @@ -0,0 +1,26 @@ +// Both revisions should pass. `borrowck` revision is a bug! +// +// revisions: wfcheck borrowck +// [wfcheck] check-pass +// [borrowck] check-fail +// [borrowck] issue: #106569 + +struct Equal<'a, 'b>(&'a &'b (), &'b &'a ()); // implies 'a == 'b + +trait Trait { type Ty; } + +impl<'x> Trait for Equal<'x, 'x> { type Ty = (); } + +trait WfCheckTrait {} + +#[cfg(wfcheck)] +impl<'a, 'b> WfCheckTrait for ( as Trait>::Ty, Equal<'a, 'b>) {} + +#[cfg(borrowck)] +fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { + //[borrowck]~^ ERROR lifetime may not live long enough + //[borrowck]~| ERROR lifetime may not live long enough + let _ = None::>; +} + +fn main() {} From f3cc860d82e22eb79f4d37b2f4d6c56fd173291e Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Fri, 31 Mar 2023 10:36:21 +0300 Subject: [PATCH 2/3] lint implied_bounds_from_trait_impl --- .../rustc_hir_analysis/src/check/wfcheck.rs | 37 +++++++++- compiler/rustc_lint_defs/src/builtin.rs | 42 +++++++++++ .../src/traits/outlives_bounds.rs | 10 +-- tests/ui/implied-bounds/from-trait-impl.rs | 39 ++++++++++ .../ui/implied-bounds/from-trait-impl.stderr | 74 +++++++++++++++++++ 5 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 tests/ui/implied-bounds/from-trait-impl.rs create mode 100644 tests/ui/implied-bounds/from-trait-impl.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f36a473aaaf3b..d18ba99d35272 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -113,10 +113,43 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( return; } - let implied_bounds = infcx.implied_bounds_tys_v2(param_env, body_def_id, assumed_wf_types); + let infcx_v2 = infcx.fork(); + let implied_bounds = infcx_v2.implied_bounds_tys_v2(param_env, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let errors_v2 = infcx_v2.resolve_regions(&outlives_env); + if errors_v2.is_empty() { + return; + } + + let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let errors_v1 = infcx.resolve_regions(&outlives_env); + if !errors_v1.is_empty() { + infcx.err_ctxt().report_region_errors(body_def_id, &errors_v1); + return; + } - let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env); + let hir_id = tcx.hir().local_def_id_to_hir_id(body_def_id); + let (lint_level, _) = tcx + .lint_level_at_node(rustc_session::lint::builtin::IMPLIED_BOUNDS_FROM_TRAIT_IMPL, hir_id); + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::IMPLIED_BOUNDS_FROM_TRAIT_IMPL, + hir_id, + tcx.def_span(body_def_id), + format!("{} is missing necessary lifetime bounds", tcx.def_descr(body_def_id.into())), + |lint| { + if !lint_level.is_error() { + lint.note( + "to get more detailed errors, use `#[deny(implied_bounds_from_trait_impl)]`", + ) + } else { + lint.note("more concrete lifetime errors are emitted below") + } + }, + ); + if lint_level.is_error() { + infcx_v2.err_ctxt().report_region_errors(body_def_id, &errors_v2); + } } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 6fe15e21d948d..d1ab8c2ca35fd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3304,6 +3304,7 @@ declare_lint_pass! { ILL_FORMED_ATTRIBUTE_INPUT, ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, IMPLIED_BOUNDS_ENTAILMENT, + IMPLIED_BOUNDS_FROM_TRAIT_IMPL, INCOMPLETE_INCLUDE, INDIRECT_STRUCTURAL_MATCH, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, @@ -4172,3 +4173,44 @@ declare_lint! { Warn, "\"invalid_parameter\" isn't a valid argument for `#[macro_export]`", } + +declare_lint! { + /// The `implied_bounds_from_trait_impl` lint detects + /// a compiler bug allowed some code to assume invalid implied lifetime bounds. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(implied_bounds_from_trait_impl)] + /// + /// trait Trait { + /// type Assoc; + /// } + /// + /// impl Trait for (X,) { + /// type Assoc = (); + /// } + /// + /// struct Foo(T) + /// where + /// T::Assoc: Clone; // any bound using `T::Assoc` + /// + /// fn func(foo: Foo<(&str,)>) { + /// let _: &'static str = foo.0.0; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// FIXME: explanataion + /// + pub IMPLIED_BOUNDS_FROM_TRAIT_IMPL, + Warn, + "item uses illegal implied bounds derived from a trait impl", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #109628 ", + reason: FutureIncompatibilityReason::FutureReleaseError, + }; +} diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 0db3c5ac5533f..1aa482e1cca71 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -30,8 +30,7 @@ pub trait InferCtxtExt<'a, 'tcx> { fn implied_bounds_tys_v2( &'a self, param_env: ty::ParamEnv<'tcx>, - _body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> BoundsV2<'a, 'tcx>; } @@ -136,11 +135,10 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { fn implied_bounds_tys_v2( &'a self, param_env: ParamEnv<'tcx>, - _body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> BoundsV2<'a, 'tcx> { - tys.into_iter() - .flat_map(move |ty| { + tys.iter() + .flat_map(move |&ty| { let ty = self.resolve_vars_if_possible(ty); let ty = OpportunisticRegionResolver::new(self).fold_ty(ty); if ty.has_infer() { diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs new file mode 100644 index 0000000000000..becadc301230a --- /dev/null +++ b/tests/ui/implied-bounds/from-trait-impl.rs @@ -0,0 +1,39 @@ +trait Trait { + type Assoc; +} + +impl Trait for (X,) { + type Assoc = (); +} + +struct Foo(T) +where + T::Assoc: Clone; // any predicate using `T::Assoc` works here + +fn func1(foo: Foo<(&str,)>) { +//~^ WARN function is missing necessary lifetime bounds +//~| WARN this was previously accepted + let _: &'static str = foo.0.0; +} + +#[deny(implied_bounds_from_trait_impl)] +fn func2(foo: Foo<(&str,)>) { +//~^ ERROR function is missing necessary lifetime bounds +//~| WARN this was previously accepted +//~| ERROR `&str` does not fulfill the required lifetime + let _: &'static str = foo.0.0; +} + +trait TestTrait {} + +impl TestTrait for [Foo<(X,)>; 1] {} +//~^ WARN implementation is missing necessary lifetime bounds +//~| WARN this was previously accepted + +#[deny(implied_bounds_from_trait_impl)] +impl TestTrait for [Foo<(X,)>; 2] {} +//~^ ERROR implementation is missing necessary lifetime bounds +//~| WARN this was previously accepted +//~| ERROR `X` may not live long enough + +fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.stderr b/tests/ui/implied-bounds/from-trait-impl.stderr new file mode 100644 index 0000000000000..fc5e34e2eed51 --- /dev/null +++ b/tests/ui/implied-bounds/from-trait-impl.stderr @@ -0,0 +1,74 @@ +warning: function is missing necessary lifetime bounds + --> $DIR/from-trait-impl.rs:13:1 + | +LL | fn func1(foo: Foo<(&str,)>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #109628 + = note: to get more detailed errors, use `#[deny(implied_bounds_from_trait_impl)]` + = note: `#[warn(implied_bounds_from_trait_impl)]` on by default + +error: function is missing necessary lifetime bounds + --> $DIR/from-trait-impl.rs:20:1 + | +LL | fn func2(foo: Foo<(&str,)>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #109628 + = note: more concrete lifetime errors are emitted below +note: the lint level is defined here + --> $DIR/from-trait-impl.rs:19:8 + | +LL | #[deny(implied_bounds_from_trait_impl)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0477]: the type `&str` does not fulfill the required lifetime + --> $DIR/from-trait-impl.rs:20:15 + | +LL | fn func2(foo: Foo<(&str,)>) { + | ^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +warning: implementation is missing necessary lifetime bounds + --> $DIR/from-trait-impl.rs:29:1 + | +LL | impl TestTrait for [Foo<(X,)>; 1] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #109628 + = note: to get more detailed errors, use `#[deny(implied_bounds_from_trait_impl)]` + +error: implementation is missing necessary lifetime bounds + --> $DIR/from-trait-impl.rs:34:1 + | +LL | impl TestTrait for [Foo<(X,)>; 2] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #109628 + = note: more concrete lifetime errors are emitted below +note: the lint level is defined here + --> $DIR/from-trait-impl.rs:33:8 + | +LL | #[deny(implied_bounds_from_trait_impl)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0310]: the parameter type `X` may not live long enough + --> $DIR/from-trait-impl.rs:34:23 + | +LL | impl TestTrait for [Foo<(X,)>; 2] {} + | ^^^^^^^^^^^^^^ ...so that the type `X` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | impl TestTrait for [Foo<(X,)>; 2] {} + | +++++++++ + +error: aborting due to 4 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0310, E0477. +For more information about an error, try `rustc --explain E0310`. From 993893a7dcda50ebe70db62d8692a21fc6c1cb2e Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Fri, 5 May 2023 21:19:28 +0300 Subject: [PATCH 3/3] rename implied bounds queries --- .../src/check/compare_impl_item.rs | 7 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 22 ++++++++------- .../src/impl_wf_check/min_specialization.rs | 2 +- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 +-- .../src/traits/coherence.rs | 2 +- .../rustc_trait_selection/src/traits/misc.rs | 2 +- .../src/traits/outlives_bounds.rs | 27 ++++++++++--------- .../query/type_op/implied_outlives_bounds.rs | 2 +- .../src/implied_outlives_bounds.rs | 14 +++++----- 10 files changed, 44 insertions(+), 40 deletions(-) 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 7384eb25f2ef7..a8f37bd594b8a 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -330,7 +330,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), + infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, wf_tys.clone()), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { @@ -724,7 +724,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), + infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, wf_tys), ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; @@ -2050,7 +2050,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 implied_bounds = + infcx.implied_bounds_tys_compat(param_env, impl_ty_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d18ba99d35272..b8ea5cda85d46 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -113,19 +113,21 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( return; } - let infcx_v2 = infcx.fork(); - let implied_bounds = infcx_v2.implied_bounds_tys_v2(param_env, &assumed_wf_types); + let infcx_compat = infcx.fork(); + + let implied_bounds = infcx.implied_bounds_tys(param_env, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let errors_v2 = infcx_v2.resolve_regions(&outlives_env); - if errors_v2.is_empty() { + let errors = infcx.resolve_regions(&outlives_env); + if errors.is_empty() { return; } - let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); + let implied_bounds = + infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let errors_v1 = infcx.resolve_regions(&outlives_env); - if !errors_v1.is_empty() { - infcx.err_ctxt().report_region_errors(body_def_id, &errors_v1); + let errors_compat = infcx_compat.resolve_regions(&outlives_env); + if !errors_compat.is_empty() { + infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat); return; } @@ -148,7 +150,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( }, ); if lint_level.is_error() { - infcx_v2.err_ctxt().report_region_errors(body_def_id, &errors_v2); + infcx.err_ctxt().report_region_errors(body_def_id, &errors); } } @@ -707,7 +709,7 @@ fn resolve_regions_with_wf_tys<'tcx>( let infcx = tcx.infer_ctxt().build(); let outlives_environment = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, id, wf_tys.clone()), + infcx.implied_bounds_tys_compat(param_env, id, wf_tys.clone()), ); let region_bound_pairs = outlives_environment.region_bound_pairs(); 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 5cca2dacb5c7f..09fc2a31ac2c3 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 @@ -176,7 +176,7 @@ fn get_impl_substs( return None; } - let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys_compat(param_env, impl1_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 6a1a2a061ddd6..68089b172b617 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -56,7 +56,7 @@ macro_rules! arena_types { rustc_middle::traits::query::NormalizationResult<'tcx> > >, - [] implied_outlives_bounds: + [] implied_outlives_bounds_compat: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, Vec> diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 786c4a32b8117..32b963b1e63cc 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1828,7 +1828,7 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } - query implied_outlives_bounds( + query implied_outlives_bounds_compat( goal: CanonicalTyGoal<'tcx> ) -> Result< &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, @@ -1837,7 +1837,7 @@ rustc_queries! { desc { "computing implied outlives bounds for `{}`", goal.value.value } } - query implied_outlives_bounds_v2( + query implied_outlives_bounds( goal: ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result<&'tcx [OutlivesBound<'tcx>], NoSolution> { desc { "computing implied outlives bounds v2 for `{}`", goal.value } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index b7690f79933d9..701f69328dc05 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -403,7 +403,7 @@ fn resolve_negative_obligation<'tcx>( let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id); let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, body_def_id, wf_tys), + infcx.implied_bounds_tys_compat(param_env, body_def_id, wf_tys), ); infcx.resolve_regions(&outlives_env).is_empty() } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 2210ef975e6c8..0ccaf80b46def 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -190,7 +190,7 @@ pub fn all_fields_implement_trait<'tcx>( // Check regions assuming the self type of the impl is WF let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys( + infcx.implied_bounds_tys_compat( param_env, parent_cause.body_id, FxIndexSet::from_iter([self_type]), diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 1aa482e1cca71..08bf260e0cf5b 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -10,28 +10,28 @@ use rustc_span::DUMMY_SP; pub use rustc_middle::traits::query::OutlivesBound; +type BoundsCompat<'a, 'tcx: 'a> = impl Iterator> + 'a; type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; -type BoundsV2<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { - fn implied_outlives_bounds( + fn implied_outlives_bounds_compat( &self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, ty: Ty<'tcx>, ) -> Vec>; - fn implied_bounds_tys( + fn implied_bounds_tys_compat( &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, tys: FxIndexSet>, - ) -> Bounds<'a, 'tcx>; + ) -> BoundsCompat<'a, 'tcx>; - fn implied_bounds_tys_v2( + fn implied_bounds_tys( &'a self, param_env: ty::ParamEnv<'tcx>, tys: &'a FxIndexSet>, - ) -> BoundsV2<'a, 'tcx>; + ) -> Bounds<'a, 'tcx>; } impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { @@ -55,7 +55,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { /// into the inference context with this body-id. /// - `ty`, the type that we are supposed to assume is WF. #[instrument(level = "debug", skip(self, param_env, body_id), ret)] - fn implied_outlives_bounds( + fn implied_outlives_bounds_compat( &self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, @@ -123,20 +123,21 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { output } - fn implied_bounds_tys( + fn implied_bounds_tys_compat( &'a self, param_env: ParamEnv<'tcx>, body_id: LocalDefId, tys: FxIndexSet>, - ) -> Bounds<'a, 'tcx> { - tys.into_iter().flat_map(move |ty| self.implied_outlives_bounds(param_env, body_id, ty)) + ) -> BoundsCompat<'a, 'tcx> { + tys.into_iter() + .flat_map(move |ty| self.implied_outlives_bounds_compat(param_env, body_id, ty)) } - fn implied_bounds_tys_v2( + fn implied_bounds_tys( &'a self, param_env: ParamEnv<'tcx>, tys: &'a FxIndexSet>, - ) -> BoundsV2<'a, 'tcx> { + ) -> Bounds<'a, 'tcx> { tys.iter() .flat_map(move |&ty| { let ty = self.resolve_vars_if_possible(ty); @@ -147,7 +148,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { return &[] as &[OutlivesBound<'_>]; } - self.tcx.implied_outlives_bounds_v2(param_env.and(ty)).unwrap_or(&[]) + self.tcx.implied_outlives_bounds(param_env.and(ty)).unwrap_or(&[]) }) .copied() } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 18d7c9b193601..287d659ab6863 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -37,6 +37,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { param_env.and(ty) }); - tcx.implied_outlives_bounds(canonicalized) + tcx.implied_outlives_bounds_compat(canonicalized) } } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 3a2da82b5465d..5b02d82ef9233 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -19,10 +19,10 @@ use smallvec::{smallvec, SmallVec}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { implied_outlives_bounds, ..*p }; - *p = Providers { implied_outlives_bounds_v2, ..*p }; + *p = Providers { implied_outlives_bounds_compat, ..*p }; } -fn implied_outlives_bounds_v2<'tcx>( +fn implied_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, goal: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Fallible<&'tcx [OutlivesBound<'tcx>]> { @@ -40,14 +40,14 @@ fn implied_outlives_bounds_v2<'tcx>( Ok(ty) }; - compute_implied_outlives_bounds_v2(tcx, goal_ty, normalize_op) + compute_implied_outlives_bounds(tcx, goal_ty, normalize_op) } /// For the sake of completeness, we should be careful when dealing with inference artifacts: /// - This function shouldn't access an InferCtxt. /// - `ty` must be fully resolved. /// - `normalize_op` must return a fully resolved type. -fn compute_implied_outlives_bounds_v2<'tcx>( +fn compute_implied_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, normalize_op: impl Fn(Ty<'tcx>) -> Fallible>, @@ -113,17 +113,17 @@ fn compute_implied_outlives_bounds_v2<'tcx>( Ok(tcx.arena.alloc_slice(&outlives_bounds)) } -fn implied_outlives_bounds<'tcx>( +fn implied_outlives_bounds_compat<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalTyGoal<'tcx>, ) -> Fallible>>> { tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| { let (param_env, ty) = key.into_parts(); - compute_implied_outlives_bounds(ocx, param_env, ty) + compute_implied_outlives_bounds_compat(ocx, param_env, ty) }) } -fn compute_implied_outlives_bounds<'tcx>( +fn compute_implied_outlives_bounds_compat<'tcx>( ocx: &ObligationCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>,