normalize each predicate inside predicates_for_generics

This commit is contained in:
Adwin White
2026-04-13 19:38:49 +08:00
parent 14196dbfa3
commit 7aa3f3ce52
10 changed files with 48 additions and 50 deletions
+4 -1
View File
@@ -3557,6 +3557,8 @@ fn find_and_report_unsatisfied_index_impl(
// Register the impl's predicates. One of these predicates
// must be unsatisfied, or else we wouldn't have gotten here
// in the first place.
let unnormalized_predicates =
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
ocx.register_obligations(traits::predicates_for_generics(
|idx, span| {
cause.clone().derived_cause(
@@ -3574,8 +3576,9 @@ fn find_and_report_unsatisfied_index_impl(
},
)
},
|pred| ocx.normalize(&cause, self.param_env, pred),
self.param_env,
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args),
unnormalized_predicates,
));
// Normalize the output type, which we can use later on as the
+2 -15
View File
@@ -423,20 +423,6 @@ pub(crate) fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec<Adjustment
}
}
/// Instantiates and normalizes the bounds for a given item
pub(crate) fn instantiate_bounds(
&self,
span: Span,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> ty::InstantiatedPredicates<'tcx> {
let bounds = self.tcx.predicates_of(def_id);
let result = bounds.instantiate(self.tcx, args);
let result = self.normalize(span, result);
debug!("instantiate_bounds(bounds={:?}, args={:?}) = {:?}", bounds, args, result);
result
}
pub(crate) fn normalize<T>(&self, span: Span, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
@@ -1426,10 +1412,11 @@ pub(crate) fn add_required_obligations_with_code(
) {
let param_env = self.param_env;
let bounds = self.instantiate_bounds(span, def_id, args);
let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args);
for obligation in traits::predicates_for_generics(
|idx, predicate_span| self.cause(span, code(idx, predicate_span)),
|pred| self.normalize(span, pred),
param_env,
bounds,
) {
+1 -1
View File
@@ -339,9 +339,9 @@ fn select_inherent_assoc_candidates(
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
let impl_bounds = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_bounds);
let impl_obligations = traits::predicates_for_generics(
|_, _| ObligationCause::dummy(),
|pred| ocx.normalize(&ObligationCause::dummy(), self.param_env, pred),
self.param_env,
impl_bounds,
);
@@ -144,8 +144,7 @@ fn confirm(
);
self.unify_receivers(self_ty, method_sig_rcvr, pick);
let (method_sig, method_predicates) =
self.normalize(self.span, (method_sig, method_predicates));
let method_sig = self.normalize(self.span, method_sig);
// Make sure nobody calls `drop()` explicitly.
self.check_for_illegal_method_calls(pick);
@@ -626,6 +625,7 @@ fn add_obligations(
);
self.cause(self.span, code)
},
|pred| self.normalize(self.call_expr.span, pred),
self.param_env,
method_predicates,
) {
+9 -5
View File
@@ -442,17 +442,21 @@ pub(super) fn lookup_method_for_operator(
// any late-bound regions appearing in its bounds.
let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args);
let InferOk { value: bounds, obligations: o } =
self.at(&obligation.cause, self.param_env).normalize(bounds);
obligations.extend(o);
assert!(!bounds.has_escaping_bound_vars());
let predicates_cause = obligation.cause.clone();
let mut normalization_obligations = PredicateObligations::new();
obligations.extend(traits::predicates_for_generics(
move |_, _| predicates_cause.clone(),
|pred| {
let InferOk { value: pred, obligations: o } =
self.at(&obligation.cause, self.param_env).normalize(pred);
normalization_obligations.extend(o);
assert!(!pred.has_escaping_bound_vars());
pred
},
self.param_env,
bounds,
));
obligations.extend(normalization_obligations);
// Also add an obligation for the method type being well-formed.
debug!(
@@ -1989,7 +1989,6 @@ fn consider_probe(
let impl_def_id = probe.item.container_id(self.tcx);
let impl_bounds =
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
// Convert the bounds into obligations.
ocx.register_obligations(traits::predicates_for_generics(
|idx, span| {
@@ -2001,6 +2000,7 @@ fn consider_probe(
);
self.cause(self.span, code)
},
|pred| ocx.normalize(cause, self.param_env, pred),
self.param_env,
impl_bounds,
));
+1 -1
View File
@@ -689,7 +689,7 @@ fn pack(self) -> Term<'tcx> {
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
/// [usize:Bar<isize>]]`.
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
#[derive(Clone, Debug)]
pub struct InstantiatedPredicates<'tcx> {
pub predicates: Vec<Clause<'tcx>>,
pub spans: Vec<Span>,
@@ -34,8 +34,8 @@
use rustc_middle::span_bug;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast,
self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast,
};
use rustc_span::Span;
use rustc_span::def_id::DefId;
@@ -177,9 +177,10 @@ pub enum TraitQueryMode {
}
/// Creates predicate obligations from the generic bounds.
#[instrument(level = "debug", skip(cause, param_env))]
#[instrument(level = "debug", skip(cause, param_env, normalize_predicate))]
pub fn predicates_for_generics<'tcx>(
cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
mut normalize_predicate: impl FnMut(Clause<'tcx>) -> Clause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_bounds: ty::InstantiatedPredicates<'tcx>,
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
@@ -187,7 +188,7 @@ pub fn predicates_for_generics<'tcx>(
cause: cause(idx, span),
recursion_depth: 0,
param_env,
predicate: clause.as_predicate(),
predicate: normalize_predicate(clause).as_predicate(),
})
}
@@ -185,12 +185,13 @@ fn fulfill_implication<'tcx>(
// Now check that the source trait ref satisfies all the where clauses of the target impl.
// This is not just for correctness; we also need this to constrain any params that may
// only be referenced via projection predicates.
let predicates = ocx.normalize(
cause,
let predicates = infcx.tcx.predicates_of(target_impl).instantiate(infcx.tcx, target_args);
let obligations = predicates_for_generics(
|_, _| cause.clone(),
|pred| ocx.normalize(cause, param_env, pred),
param_env,
infcx.tcx.predicates_of(target_impl).instantiate(infcx.tcx, target_args),
predicates,
);
let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
ocx.register_obligations(obligations);
let errors = ocx.evaluate_obligations_error_on_ambiguity();
@@ -315,12 +316,14 @@ pub(super) fn specializes(
// Now check that the source trait ref satisfies all the where clauses of the target impl.
// This is not just for correctness; we also need this to constrain any params that may
// only be referenced via projection predicates.
let predicates = ocx.normalize(
cause,
let predicates =
infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args);
let obligations = predicates_for_generics(
|_, _| cause.clone(),
|pred| ocx.normalize(cause, param_env, pred),
param_env,
infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args),
predicates,
);
let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
ocx.register_obligations(obligations);
let errors = ocx.evaluate_obligations_error_on_ambiguity();
@@ -9,18 +9,6 @@ help: consider restricting type parameter `T` with trait `X`
LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
| ++++++++++++++++++
error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:18:5
|
LL | <(i32,) as X<i32>>::f("abc");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> X<'b, i32>` is not implemented for `i32`
|
help: the trait `X<'_, T>` is implemented for `(S,)`
--> $DIR/hr-associated-type-bound-param-6.rs:12:1
|
LL | impl<S, T> X<'_, T> for (S,) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:18:18
|
@@ -41,6 +29,18 @@ LL | for<'b> T: X<'b, T>,
LL | fn f(x: &<T as X<'_, T>>::U) {
| - required by a bound in this associated function
error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:18:5
|
LL | <(i32,) as X<i32>>::f("abc");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> X<'b, i32>` is not implemented for `i32`
|
help: the trait `X<'_, T>` is implemented for `(S,)`
--> $DIR/hr-associated-type-bound-param-6.rs:12:1
|
LL | impl<S, T> X<'_, T> for (S,) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `i32: X<'_, i32>` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:18:27
|