Remove fully_normalize
This commit is contained in:
parent
0c81f94b9a
commit
2c8bbeebf1
@ -5,8 +5,7 @@ use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifie
|
|||||||
use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
|
||||||
use rustc_session::{declare_lint, declare_lint_pass};
|
use rustc_session::{declare_lint, declare_lint_pass};
|
||||||
use rustc_span::{symbol::kw, Span};
|
use rustc_span::{symbol::kw, Span};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
|
||||||
|
|
||||||
use crate::{LateContext, LateLintPass, LintContext};
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
|
|
||||||
@ -130,24 +129,26 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||||||
.iter_instantiated_copied(cx.tcx, proj.projection_term.args)
|
.iter_instantiated_copied(cx.tcx, proj.projection_term.args)
|
||||||
{
|
{
|
||||||
let assoc_pred = assoc_pred.fold_with(proj_replacer);
|
let assoc_pred = assoc_pred.fold_with(proj_replacer);
|
||||||
let Ok(assoc_pred) = traits::fully_normalize(
|
|
||||||
infcx,
|
|
||||||
traits::ObligationCause::dummy(),
|
|
||||||
cx.param_env,
|
|
||||||
assoc_pred,
|
|
||||||
) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If that predicate doesn't hold modulo regions (but passed during type-check),
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
// then we must've taken advantage of the hack in `project_and_unify_types` where
|
let assoc_pred =
|
||||||
// we replace opaques with inference vars. Emit a warning!
|
ocx.normalize(&traits::ObligationCause::dummy(), cx.param_env, assoc_pred);
|
||||||
if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new(
|
if !ocx.select_all_or_error().is_empty() {
|
||||||
|
// Can't normalize for some reason...?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocx.register_obligation(traits::Obligation::new(
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
traits::ObligationCause::dummy(),
|
traits::ObligationCause::dummy(),
|
||||||
cx.param_env,
|
cx.param_env,
|
||||||
assoc_pred,
|
assoc_pred,
|
||||||
)) {
|
));
|
||||||
|
|
||||||
|
// If that predicate doesn't hold modulo regions (but passed during type-check),
|
||||||
|
// then we must've taken advantage of the hack in `project_and_unify_types` where
|
||||||
|
// we replace opaques with inference vars. Emit a warning!
|
||||||
|
if !ocx.select_all_or_error().is_empty() {
|
||||||
// If it's a trait bound and an opaque that doesn't satisfy it,
|
// If it's a trait bound and an opaque that doesn't satisfy it,
|
||||||
// then we can emit a suggestion to add the bound.
|
// then we can emit a suggestion to add the bound.
|
||||||
let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
|
let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
|
||||||
|
@ -271,13 +271,14 @@ fn do_normalize_predicates<'tcx>(
|
|||||||
// them here too, and we will remove this function when
|
// them here too, and we will remove this function when
|
||||||
// we move over to lazy normalization *anyway*.
|
// we move over to lazy normalization *anyway*.
|
||||||
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
||||||
let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
|
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
Ok(predicates) => predicates,
|
let predicates = ocx.normalize(&cause, elaborated_env, predicates);
|
||||||
Err(errors) => {
|
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
|
let errors = ocx.select_all_or_error();
|
||||||
return Err(reported);
|
if !errors.is_empty() {
|
||||||
}
|
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||||
};
|
return Err(reported);
|
||||||
|
}
|
||||||
|
|
||||||
debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
|
debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
|
||||||
|
|
||||||
@ -465,37 +466,6 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal())
|
ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalize a type and process all resulting obligations, returning any errors.
|
|
||||||
///
|
|
||||||
/// FIXME(-Znext-solver): This should be replaced by `At::deeply_normalize`
|
|
||||||
/// which has the same behavior with the new solver. Because using a separate
|
|
||||||
/// fulfillment context worsens caching in the old solver, `At::deeply_normalize`
|
|
||||||
/// is still lazy with the old solver as it otherwise negatively impacts perf.
|
|
||||||
#[instrument(skip_all)]
|
|
||||||
pub fn fully_normalize<'tcx, T>(
|
|
||||||
infcx: &InferCtxt<'tcx>,
|
|
||||||
cause: ObligationCause<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
value: T,
|
|
||||||
) -> Result<T, Vec<FulfillmentError<'tcx>>>
|
|
||||||
where
|
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
|
||||||
{
|
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
|
||||||
debug!(?value);
|
|
||||||
let normalized_value = ocx.normalize(&cause, param_env, value);
|
|
||||||
debug!(?normalized_value);
|
|
||||||
debug!("select_all_or_error start");
|
|
||||||
let errors = ocx.select_all_or_error();
|
|
||||||
if !errors.is_empty() {
|
|
||||||
return Err(errors);
|
|
||||||
}
|
|
||||||
debug!("select_all_or_error complete");
|
|
||||||
let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
|
|
||||||
debug!(?resolved_value);
|
|
||||||
Ok(resolved_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
|
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
|
||||||
/// returns true, then either normalize encountered an error or one of the predicates did not
|
/// returns true, then either normalize encountered an error or one of the predicates did not
|
||||||
/// hold. Used when creating vtables to check for unsatisfiable methods.
|
/// hold. Used when creating vtables to check for unsatisfiable methods.
|
||||||
|
@ -42,11 +42,9 @@ impl<'tcx> At<'_, 'tcx> {
|
|||||||
/// same goals in both a temporary and the shared context which negatively impacts
|
/// same goals in both a temporary and the shared context which negatively impacts
|
||||||
/// performance as these don't share caching.
|
/// performance as these don't share caching.
|
||||||
///
|
///
|
||||||
/// FIXME(-Znext-solver): This has the same behavior as `traits::fully_normalize`
|
/// FIXME(-Znext-solver): For performance reasons, we currently reuse an existing
|
||||||
/// in the new solver, but because of performance reasons, we currently reuse an
|
/// fulfillment context in the old solver. Once we have removed the old solver, we
|
||||||
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with
|
/// can remove the `fulfill_cx` parameter on this function.
|
||||||
/// the old solver or have removed the old solver, remove `traits::fully_normalize` and
|
|
||||||
/// rename this function to `At::fully_normalize`.
|
|
||||||
fn deeply_normalize<T, E>(
|
fn deeply_normalize<T, E>(
|
||||||
self,
|
self,
|
||||||
value: T,
|
value: T,
|
||||||
|
@ -18,9 +18,7 @@ use crate::error_reporting::traits::to_pretty_impl_header;
|
|||||||
use crate::errors::NegativePositiveConflict;
|
use crate::errors::NegativePositiveConflict;
|
||||||
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||||
use crate::traits::select::IntercrateAmbiguityCause;
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::{
|
use crate::traits::{coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt};
|
||||||
self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt,
|
|
||||||
};
|
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::{codes::*, Diag, EmissionGuarantee};
|
use rustc_errors::{codes::*, Diag, EmissionGuarantee};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
@ -219,19 +217,17 @@ fn fulfill_implication<'tcx>(
|
|||||||
param_env, source_trait_ref, target_impl
|
param_env, source_trait_ref, target_impl
|
||||||
);
|
);
|
||||||
|
|
||||||
let source_trait_ref =
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
match traits::fully_normalize(infcx, ObligationCause::dummy(), param_env, source_trait_ref)
|
let source_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, source_trait_ref);
|
||||||
{
|
|
||||||
Ok(source_trait_ref) => source_trait_ref,
|
|
||||||
Err(_errors) => {
|
|
||||||
infcx.dcx().span_delayed_bug(
|
|
||||||
infcx.tcx.def_span(source_impl),
|
|
||||||
format!("failed to fully normalize {source_trait_ref}"),
|
|
||||||
);
|
|
||||||
source_trait_ref
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if !ocx.select_all_or_error().is_empty() {
|
||||||
|
infcx.dcx().span_delayed_bug(
|
||||||
|
infcx.tcx.def_span(source_impl),
|
||||||
|
format!("failed to fully normalize {source_trait_ref}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let source_trait_ref = infcx.resolve_vars_if_possible(source_trait_ref);
|
||||||
let source_trait = ImplSubject::Trait(source_trait_ref);
|
let source_trait = ImplSubject::Trait(source_trait_ref);
|
||||||
|
|
||||||
let selcx = SelectionContext::new(infcx);
|
let selcx = SelectionContext::new(infcx);
|
||||||
@ -253,9 +249,6 @@ fn fulfill_implication<'tcx>(
|
|||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Needs to be `in_snapshot` because this function is used to rebase
|
|
||||||
// generic parameters, which may happen inside of a select within a probe.
|
|
||||||
let ocx = ObligationCtxt::new(infcx);
|
|
||||||
// attempt to prove all of the predicates for impl2 given those for impl1
|
// attempt to prove all of the predicates for impl2 given those for impl1
|
||||||
// (which are packed up in penv)
|
// (which are packed up in penv)
|
||||||
ocx.register_obligations(obligations.chain(more_obligations));
|
ocx.register_obligations(obligations.chain(more_obligations));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user