Nits and formatting

This commit is contained in:
Michael Goulet 2024-06-03 09:27:48 -04:00
parent 1e72c7f536
commit a41c44f21c
17 changed files with 130 additions and 142 deletions

View file

@ -6,8 +6,8 @@ use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
use rustc_infer::traits::{
self, FromSolverError, FulfillmentErrorLike, MismatchedProjectionTypes, Obligation,
ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause,
ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
};
use rustc_middle::bug;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -31,7 +31,7 @@ use super::{Certainty, InferCtxtEvalExt};
///
/// It is also likely that we want to use slightly different datastructures
/// here as this will have to deal with far more root goals than `evaluate_all`.
pub struct FulfillmentCtxt<'tcx, E: FulfillmentErrorLike<'tcx>> {
pub struct FulfillmentCtxt<'tcx, E: 'tcx> {
obligations: ObligationStorage<'tcx>,
/// The snapshot in which this context was created. Using the context
@ -93,7 +93,7 @@ impl<'tcx> ObligationStorage<'tcx> {
}
}
impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> {
impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> {
pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> {
assert!(
infcx.next_trait_solver(),
@ -123,8 +123,9 @@ impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> {
}
}
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> TraitEngine<'tcx, E>
for FulfillmentCtxt<'tcx, E>
impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentCtxt<'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
#[instrument(level = "trace", skip(self, infcx))]
fn register_predicate_obligation(

View file

@ -12,7 +12,6 @@
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::FulfillmentErrorLike as _;
use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult};

View file

@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::marker::PhantomData;
use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
@ -6,7 +7,7 @@ use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::infer::at::At;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, Obligation, TraitEngine};
use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
@ -16,14 +17,11 @@ use super::{FulfillmentCtxt, NextSolverError};
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
/// its input to be already fully resolved.
pub fn deeply_normalize<
'tcx,
pub fn deeply_normalize<'tcx, T, E>(at: At<'_, 'tcx>, value: T) -> Result<T, Vec<E>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
>(
at: At<'_, 'tcx>,
value: T,
) -> Result<T, Vec<E>> {
{
assert!(!value.has_escaping_bound_vars());
deeply_normalize_with_skipped_universes(at, value, vec![])
}
@ -34,15 +32,15 @@ pub fn deeply_normalize<
/// Additionally takes a list of universes which represents the binders which have been
/// entered before passing `value` to the function. This is currently needed for
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
pub fn deeply_normalize_with_skipped_universes<
'tcx,
T: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
>(
pub fn deeply_normalize_with_skipped_universes<'tcx, T, E>(
at: At<'_, 'tcx>,
value: T,
universes: Vec<Option<UniverseIndex>>,
) -> Result<T, Vec<E>> {
) -> Result<T, Vec<E>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
let mut folder =
NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
@ -50,7 +48,7 @@ pub fn deeply_normalize_with_skipped_universes<
value.try_fold_with(&mut folder)
}
struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> {
struct NormalizationFolder<'me, 'tcx, E> {
at: At<'me, 'tcx>,
fulfill_cx: FulfillmentCtxt<'tcx, E>,
depth: usize,
@ -58,7 +56,10 @@ struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> {
_errors: PhantomData<E>,
}
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<'_, 'tcx, E> {
impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
@ -150,8 +151,9 @@ impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<
}
}
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> FallibleTypeFolder<TyCtxt<'tcx>>
for NormalizationFolder<'_, 'tcx, E>
impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>> + Debug,
{
type Error = Vec<E>;

View file

@ -21,7 +21,6 @@ use rustc_infer::infer::canonical::{
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::RegionResolutionError;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::FulfillmentErrorLike;
use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::traits::query::NoSolution;
@ -32,10 +31,9 @@ use rustc_middle::ty::Variance;
use rustc_middle::ty::{self, Ty, TyCtxt};
#[extension(pub trait TraitEngineExt<'tcx, E>)]
impl<
'tcx,
impl<'tcx, E> dyn TraitEngine<'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
> dyn TraitEngine<'tcx, E>
{
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
if infcx.next_trait_solver() {
@ -73,7 +71,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> {
impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
where
E: FulfillmentErrorLike<'tcx>,
E: 'tcx,
{
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
@ -231,7 +229,20 @@ where
) -> Vec<RegionResolutionError<'tcx>> {
self.infcx.resolve_regions(outlives_env)
}
}
impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
pub fn assumed_wf_types_and_report_errors(
&self,
param_env: ty::ParamEnv<'tcx>,
def_id: LocalDefId,
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
self.assumed_wf_types(param_env, def_id)
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
}
}
impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> {
pub fn make_canonicalized_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
@ -249,17 +260,6 @@ where
}
}
impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
pub fn assumed_wf_types_and_report_errors(
&self,
param_env: ty::ParamEnv<'tcx>,
def_id: LocalDefId,
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
self.assumed_wf_types(param_env, def_id)
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
}
}
impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,

View file

@ -6,7 +6,7 @@ use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, ProjectionCacheKey};
use rustc_infer::traits::{FromSolverError, ProjectionCacheKey};
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
use rustc_middle::bug;
use rustc_middle::mir::interpret::ErrorHandled;
@ -50,7 +50,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
/// along. Once all type inference constraints have been generated, the
/// method `select_all_or_error` can be used to report any remaining
/// ambiguous cases as errors.
pub struct FulfillmentContext<'tcx, E: FulfillmentErrorLike<'tcx>> {
pub struct FulfillmentContext<'tcx, E: 'tcx> {
/// A list of all obligations that have been registered with this
/// fulfillment context.
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
@ -78,7 +78,10 @@ pub struct PendingPredicateObligation<'tcx> {
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'tcx, E> {
impl<'tcx, E> FulfillmentContext<'tcx, E>
where
E: FromSolverError<'tcx, OldSolverError<'tcx>>,
{
/// Creates a new fulfillment context.
pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
assert!(
@ -106,8 +109,11 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t
// FIXME: if we kept the original cache key, we could mark projection
// obligations as complete for the projection cache here.
let errors: Vec<E> =
outcome.errors.into_iter().map(|err| E::from_solver_error(infcx, err)).collect();
let errors: Vec<E> = outcome
.errors
.into_iter()
.map(|err| E::from_solver_error(infcx, OldSolverError(err)))
.collect();
debug!(
"select({} predicates remaining, {} errors) done",
@ -119,8 +125,9 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t
}
}
impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E>
for FulfillmentContext<'tcx, E>
impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E>
where
E: FromSolverError<'tcx, OldSolverError<'tcx>>,
{
#[inline]
fn register_predicate_obligation(
@ -144,7 +151,7 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E>
self.predicates
.to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
.into_iter()
.map(|err| E::from_solver_error(infcx, err))
.map(|err| E::from_solver_error(infcx, OldSolverError(err)))
.collect()
}
@ -843,22 +850,25 @@ fn args_infer_vars<'a, 'tcx>(
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
}
pub type OldSolverError<'tcx> = Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>;
#[derive(Debug)]
pub struct OldSolverError<'tcx>(
Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
);
impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
let mut iter = error.backtrace.into_iter();
let mut iter = error.0.backtrace.into_iter();
let obligation = iter.next().unwrap().obligation;
// The root obligation is the last item in the backtrace - if there's only
// one item, then it's the same as the main obligation
let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
FulfillmentError::new(obligation, error.error, root_obligation)
FulfillmentError::new(obligation, error.0.error, root_obligation)
}
}
impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
match error.error {
match error.0.error {
FulfillmentErrorCode::Select(_)
| FulfillmentErrorCode::Project(_)
| FulfillmentErrorCode::Subtype(_, _)

View file

@ -71,37 +71,6 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh
pub use rustc_infer::traits::*;
/// A trait error with most of its information removed. This is the error
/// returned by an [`ObligationCtxt`] by default, and suitable if you just
/// want to see if a predicate holds, and don't particularly care about the
/// error itself (except for if it's an ambiguity or true error).
///
/// use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`].
#[derive(Clone, Debug)]
pub enum ScrubbedTraitError<'tcx> {
/// A real error. This goal definitely does not hold.
TrueError,
/// An ambiguity. This goal may hold if further inference is done.
Ambiguity,
/// An old-solver-style cycle error, which will fatal.
Cycle(Vec<PredicateObligation<'tcx>>),
}
impl<'tcx> ScrubbedTraitError<'tcx> {
fn is_true_error(&self) -> bool {
match self {
ScrubbedTraitError::TrueError => true,
ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
}
}
}
impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError<'tcx> {
fn is_true_error(&self) -> bool {
self.is_true_error()
}
}
pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx>,
@ -133,12 +102,6 @@ impl<'tcx> FulfillmentError<'tcx> {
}
}
impl<'tcx> FulfillmentErrorLike<'tcx> for FulfillmentError<'tcx> {
fn is_true_error(&self) -> bool {
self.is_true_error()
}
}
impl<'tcx> Debug for FulfillmentError<'tcx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)

View file

@ -46,14 +46,15 @@ impl<'tcx> At<'_, 'tcx> {
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with
/// 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: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
>(
fn deeply_normalize<T, E>(
self,
value: T,
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
) -> Result<T, Vec<E>> {
) -> Result<T, Vec<E>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
if self.infcx.next_trait_solver() {
crate::solve::deeply_normalize(self, value)
} else {

View file

@ -1,8 +1,6 @@
use crate::solve;
use crate::traits::query::NoSolution;
use crate::traits::wf;
use crate::traits::ObligationCtxt;
use crate::traits::ScrubbedTraitError;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
@ -263,11 +261,9 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
// Need to manually normalize in the new solver as `wf::obligations` does not.
if ocx.infcx.next_trait_solver() {
ty_a = solve::deeply_normalize(
ocx.infcx.at(&ObligationCause::dummy(), param_env),
ty_a,
)
.map_err(|_errs: Vec<ScrubbedTraitError<'tcx>>| NoSolution)?;
ty_a = ocx
.deeply_normalize(&ObligationCause::dummy(), param_env, ty_a)
.map_err(|_| NoSolution)?;
}
let mut components = smallvec![];
push_outlives_components(tcx, ty_a, &mut components);

View file

@ -1,5 +1,5 @@
use rustc_infer::infer::at::At;
use rustc_infer::traits::{FulfillmentErrorLike, TraitEngine};
use rustc_infer::traits::TraitEngine;
use rustc_macros::extension;
use rustc_middle::ty::{self, Ty};
@ -7,7 +7,7 @@ use crate::traits::{NormalizeExt, Obligation};
#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
impl<'tcx> At<'_, 'tcx> {
fn structurally_normalize<E: FulfillmentErrorLike<'tcx>>(
fn structurally_normalize<E: 'tcx>(
&self,
ty: Ty<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,