mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #155236 - adwinwhite:refactor-predicates-for-generics, r=lcnr
Normalize individual predicate of `InstantiatedPredicates` inside `predicates_for_generics` This is a cleanup to better land rust-lang/rust#155083. It allows us to wrap individual clause in `Unnormalized` wrapper. See [this comment](https://github.com/rust-lang/rust/pull/155083#discussion_r3072219035) Besides that, this PR also adds missing normalization in some cases. r? @lcnr
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -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,
|
||||
));
|
||||
|
||||
@@ -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
|
||||
|
|
||||
|
||||
Reference in New Issue
Block a user