From 707c4f967e4d6c68252eb784844a10a3613bde61 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Fri, 15 Dec 2023 06:02:40 +0000 Subject: [PATCH] unify query canonicalization mode --- .../src/infer/canonical/canonicalizer.rs | 83 ++++++------------- .../src/traits/outlives_bounds.rs | 3 +- .../src/traits/query/evaluate_obligation.rs | 6 +- .../src/traits/query/normalize.rs | 5 +- .../src/traits/query/type_op/mod.rs | 7 +- .../hrtb-cache-issue-54302.stderr | 2 +- .../trait-bounds/issue-59311.stderr | 2 +- tests/ui/nll/issue-54302.stderr | 2 +- 8 files changed, 35 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 5b00ef42211e8..fb703f3857091 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -41,7 +41,33 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.canonicalize_query_with_mode(value, query_state, &CanonicalizeAllFreeRegions) + let (param_env, value) = value.into_parts(); + let param_env = self.tcx.canonical_param_env_cache.get_or_insert( + self.tcx, + param_env, + query_state, + |tcx, param_env, query_state| { + // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the + // `param_env` beacause they are treated differently by trait selection. + Canonicalizer::canonicalize( + param_env, + None, + tcx, + &CanonicalizeFreeRegionsOtherThanStatic, + query_state, + ) + }, + ); + + Canonicalizer::canonicalize_with_base( + param_env, + value, + Some(self), + self.tcx, + &CanonicalizeAllFreeRegions, + query_state, + ) + .unchecked_map(|(param_env, value)| param_env.and(value)) } /// Canonicalizes a query *response* `V`. When we canonicalize a @@ -96,61 +122,6 @@ impl<'tcx> InferCtxt<'tcx> { &mut query_state, ) } - - /// A variant of `canonicalize_query` that does not - /// canonicalize `'static`. This is useful when - /// the query implementation can perform more efficient - /// handling of `'static` regions (e.g. trait evaluation). - pub fn canonicalize_query_keep_static( - &self, - value: ty::ParamEnvAnd<'tcx, V>, - query_state: &mut OriginalQueryValues<'tcx>, - ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>> - where - V: TypeFoldable>, - { - self.canonicalize_query_with_mode( - value, - query_state, - &CanonicalizeFreeRegionsOtherThanStatic, - ) - } - - fn canonicalize_query_with_mode( - &self, - value: ty::ParamEnvAnd<'tcx, V>, - query_state: &mut OriginalQueryValues<'tcx>, - canonicalize_region_mode: &dyn CanonicalizeMode, - ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>> - where - V: TypeFoldable>, - { - let (param_env, value) = value.into_parts(); - let base = self.tcx.canonical_param_env_cache.get_or_insert( - self.tcx, - param_env, - query_state, - |tcx, param_env, query_state| { - Canonicalizer::canonicalize( - param_env, - None, - tcx, - &CanonicalizeFreeRegionsOtherThanStatic, - query_state, - ) - }, - ); - - Canonicalizer::canonicalize_with_base( - base, - value, - Some(self), - self.tcx, - canonicalize_region_mode, - query_state, - ) - .unchecked_map(|(param_env, value)| param_env.and(value)) - } } /// Controls how we canonicalize "free regions" that are not inference diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 7513f88cfc3cf..3b5a25814d38a 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -65,8 +65,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { assert!(!ty.has_non_region_infer()); let mut canonical_var_values = OriginalQueryValues::default(); - let canonical_ty = - self.canonicalize_query_keep_static(param_env.and(ty), &mut canonical_var_values); + let canonical_ty = self.canonicalize_query(param_env.and(ty), &mut canonical_var_values); let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else { return vec![]; }; diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index d812d537d8c1d..31e34096fb003 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -87,10 +87,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { }) } else { assert!(!self.intercrate); - let c_pred = self.canonicalize_query_keep_static( - param_env.and(obligation.predicate), - &mut _orig_values, - ); + let c_pred = + self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values); self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 4728fcf3301c0..b0364ac4ca504 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -275,10 +275,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> let data = data.try_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); - // HACK(matthewjasper) `'static` is special-cased in selection, - // so we cannot canonicalize it. - let c_data = infcx - .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); + let c_data = infcx.canonicalize_query(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); let result = match kind { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 272f1a54f819b..02024ede7eed5 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -111,14 +111,9 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't return Ok((result, None, vec![], Certainty::Proven)); } - // FIXME(#33684) -- We need to use - // `canonicalize_query_keep_static` here because of things - // like the subtype query, which go awry around - // `'static` otherwise. let mut canonical_var_values = OriginalQueryValues::default(); let old_param_env = query_key.param_env; - let canonical_self = - infcx.canonicalize_query_keep_static(query_key, &mut canonical_var_values); + let canonical_self = infcx.canonicalize_query(query_key, &mut canonical_var_values); let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?; let InferOk { value, obligations } = infcx diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr index 7f81ee331bf65..186af160d9083 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr @@ -4,7 +4,7 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | - = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: `&str` must implement `Deserialize<'0>`, for any lifetime `'0`... = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index 28c259be35f6f..e50aad876d8c6 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -12,7 +12,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^ | - = note: could not prove `for<'a> &'a V: 'static` + = note: could not prove `for<'a> &'a V: 'b` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-54302.stderr b/tests/ui/nll/issue-54302.stderr index 269739af6026d..a1e2d40142907 100644 --- a/tests/ui/nll/issue-54302.stderr +++ b/tests/ui/nll/issue-54302.stderr @@ -4,7 +4,7 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | - = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: `&str` must implement `Deserialize<'0>`, for any lifetime `'0`... = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to 1 previous error