Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive },
))),
self.prove_clause(
ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::PredicatePolarity::Positive,
}),
locations,
category,
);
Expand All @@ -151,31 +152,32 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
for (predicate, span) in instantiated_predicates {
debug!(?span, ?predicate);
let category = ConstraintCategory::Predicate(span);
let predicate = self.normalize_with_category(predicate, locations, category);
self.prove_predicate(predicate, locations, category);
let clause = self.normalize_with_category(predicate, locations, category);
self.prove_clause(clause, locations, category);
}
}

pub(super) fn prove_predicates(
pub(super) fn prove_clauses(
&mut self,
predicates: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + std::fmt::Debug>,
clauses: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Clause<'tcx>> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
for predicate in predicates {
self.prove_predicate(predicate, locations, category);
for clause in clauses {
self.prove_clause(clause, locations, category);
}
}

#[instrument(skip(self), level = "debug")]
pub(super) fn prove_predicate(
pub(super) fn prove_clause(
&mut self,
predicate: impl Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + std::fmt::Debug,
clause: impl Upcast<TyCtxt<'tcx>, ty::Clause<'tcx>> + std::fmt::Debug,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
let param_env = self.infcx.param_env;
let predicate = predicate.upcast(self.tcx());
// Upcast to a `Clause`, then to a `Predicate`.
let predicate = clause.upcast(self.tcx()).upcast(self.tcx());
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
locations,
category,
Expand Down
31 changes: 14 additions & 17 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,12 +820,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// don't have to check it twice.
//
// See #91068 for an example.
self.prove_predicates(
unnormalized_sig.inputs_and_output.iter().map(|ty| {
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
ty.into(),
)))
}),
self.prove_clauses(
unnormalized_sig
.inputs_and_output
.iter()
.map(|ty| ty::ClauseKind::WellFormed(ty.into())),
term_location.to_locations(),
ConstraintCategory::Boring,
);
Expand All @@ -835,12 +834,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// with built-in `Fn` implementations, since the impl may not be
// well-formed itself.
if sig != unnormalized_sig {
self.prove_predicates(
sig.inputs_and_output.iter().map(|ty| {
ty::Binder::dummy(ty::PredicateKind::Clause(
ty::ClauseKind::WellFormed(ty.into()),
))
}),
self.prove_clauses(
sig.inputs_and_output
.iter()
.map(|ty| ty::ClauseKind::WellFormed(ty.into())),
term_location.to_locations(),
ConstraintCategory::Boring,
);
Expand Down Expand Up @@ -996,8 +993,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {

Rvalue::Repeat(operand, len) => {
let array_ty = rvalue.ty(self.body.local_decls(), tcx);
self.prove_predicate(
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
self.prove_clause(
ty::ClauseKind::WellFormed(array_ty.into()),
Locations::Single(location),
ConstraintCategory::Boring,
);
Expand Down Expand Up @@ -1082,7 +1079,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
src_sig,
);
let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
self.prove_predicate(
self.prove_clause(
ty::ClauseKind::WellFormed(src_ty.into()),
location.to_locations(),
ConstraintCategory::Cast {
Expand Down Expand Up @@ -1120,7 +1117,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// well-formed, because we don't enforce that via the WF of FnDef
// types normally. This should be removed when we improve the tracking
// of implied bounds of fn signatures.
self.prove_predicate(
self.prove_clause(
ty::ClauseKind::WellFormed(src_ty.into()),
location.to_locations(),
ConstraintCategory::Cast {
Expand Down Expand Up @@ -1833,7 +1830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);

assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
self.prove_predicates(
self.prove_clauses(
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
locations,
ConstraintCategory::Boring,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2635,7 +2635,7 @@ fn param_env_with_gat_bounds<'tcx>(
) -> ty::ParamEnv<'tcx> {
let param_env = tcx.param_env(impl_ty.def_id);
let container_id = impl_ty.container_id(tcx);
let mut predicates = param_env.caller_bounds().to_vec();
let mut clauses = param_env.caller_bounds().to_vec();

// for RPITITs, we should install predicates that allow us to project all
// of the RPITITs associated with the same body. This is because checking
Expand Down Expand Up @@ -2732,7 +2732,7 @@ fn param_env_with_gat_bounds<'tcx>(
//
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
}
_ => predicates.push(
_ => clauses.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_term: ty::AliasTerm::new_from_def_id(
Expand All @@ -2749,7 +2749,7 @@ fn param_env_with_gat_bounds<'tcx>(
};
}

ty::ParamEnv::new(tcx.mk_clauses(&predicates))
ty::ParamEnv::new(tcx.mk_clauses(&clauses))
}

/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`,
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,19 +566,18 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
fn augment_param_env<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
new_predicates: Option<&FxIndexSet<ty::Clause<'tcx>>>,
new_clauses: Option<&FxIndexSet<ty::Clause<'tcx>>>,
) -> ty::ParamEnv<'tcx> {
let Some(new_predicates) = new_predicates else {
let Some(new_clauses) = new_clauses else {
return param_env;
};

if new_predicates.is_empty() {
if new_clauses.is_empty() {
return param_env;
}

let bounds = tcx.mk_clauses_from_iter(
param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
);
let bounds = tcx
.mk_clauses_from_iter(param_env.caller_bounds().iter().chain(new_clauses.iter().copied()));
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
ty::ParamEnv::new(bounds)
Expand Down
26 changes: 14 additions & 12 deletions compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ fn check_predicates<'tcx>(
impl2_args: GenericArgsRef<'tcx>,
span: Span,
) -> Result<(), ErrorGuaranteed> {
let impl1_predicates: Vec<_> = traits::elaborate(
let impl1_clauses: Vec<(ty::Clause<'_>, _)> = traits::elaborate(
tcx,
tcx.predicates_of(impl1_def_id)
.instantiate(tcx, impl1_args)
Expand All @@ -333,7 +333,7 @@ fn check_predicates<'tcx>(
)
.collect();

let mut impl2_predicates = if impl2_node.is_from_trait() {
let mut impl2_clauses: Vec<ty::Clause<'_>> = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
// assumptions.
Vec::new()
Expand All @@ -343,11 +343,11 @@ fn check_predicates<'tcx>(
tcx.predicates_of(impl2_node.def_id())
.instantiate(tcx, impl2_args)
.into_iter()
.map(|(c, _s)| c.skip_norm_wip().as_predicate()),
.map(|(c, _s)| c.skip_norm_wip()),
)
.collect()
};
debug!(?impl1_predicates, ?impl2_predicates);
debug!(?impl1_clauses, ?impl2_clauses);

// Since impls of always applicable traits don't get to assume anything, we
// can also assume their supertraits apply.
Expand All @@ -364,7 +364,7 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
let always_applicable_traits = impl1_predicates
let always_applicable_traits = impl1_clauses
.iter()
.copied()
.filter(|&(clause, _span)| {
Expand All @@ -373,7 +373,7 @@ fn check_predicates<'tcx>(
Some(TraitSpecializationKind::AlwaysApplicable)
)
})
.map(|(c, _span)| c.as_predicate());
.map(|(c, _span)| c);

// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).instantiate_identity().skip_norm_wip().args {
Expand All @@ -386,15 +386,17 @@ fn check_predicates<'tcx>(
.unwrap();

assert!(!obligations.has_infer());
impl2_predicates
.extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
impl2_clauses.extend(
traits::elaborate(tcx, obligations)
.filter_map(|obligation| obligation.predicate.as_clause()),
)
}
impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
impl2_clauses.extend(traits::elaborate(tcx, always_applicable_traits));

let mut res = Ok(());
for (clause, span) in impl1_predicates {
if !impl2_predicates.iter().any(|&pred2| clause.as_predicate() == pred2) {
res = res.and(check_specialization_on(tcx, clause, span))
for (clause1, span) in impl1_clauses {
if !impl2_clauses.iter().any(|&clause2| clause1 == clause2) {
res = res.and(check_specialization_on(tcx, clause1, span))
}
}
res
Expand Down
49 changes: 22 additions & 27 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx
.explicit_item_self_bounds(def_id)
.iter_instantiated_copied(self.tcx, args)
.map(Unnormalized::skip_norm_wip)
.map(|(c, s)| (c.as_predicate(), s)),
.map(Unnormalized::skip_norm_wip),
),
ty::Dynamic(object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
Expand All @@ -319,7 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_kind,
self.obligations_for_self_ty(vid)
.into_iter()
.map(|obl| (obl.predicate, obl.cause.span)),
.filter_map(|obl| Some((obl.predicate.as_clause()?, obl.cause.span))),
),
ty::FnPtr(sig_tys, hdr) => match closure_kind {
hir::ClosureKind::Closure => {
Expand All @@ -338,36 +337,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
expected_ty: Ty<'tcx>,
closure_kind: hir::ClosureKind,
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
clauses: impl DoubleEndedIterator<Item = (ty::Clause<'tcx>, Span)>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let mut expected_sig = None;
let mut expected_kind = None;

for (pred, span) in traits::elaborate(
for (clause, span) in traits::elaborate(
self.tcx,
// Reverse the obligations here, since `elaborate_*` uses a stack,
// and we want to keep inference generally in the same order of
// the registered obligations.
predicates.rev(),
clauses.rev(),
)
// We only care about self bounds
.filter_only_self()
{
debug!(?pred);
let bound_predicate = pred.kind();
debug!(?clause);
let bound_clause = clause.kind();

// Given a Projection predicate, we can potentially infer
// the complete signature.
// Given a Projection clause, we can potentially infer the complete signature.
if expected_sig.is_none()
&& let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_predicate)) =
bound_predicate.skip_binder()
&& let ty::ClauseKind::Projection(proj_clause) = bound_clause.skip_binder()
{
let inferred_sig = self.normalize(
span,
Unnormalized::new_wip(self.deduce_sig_from_projection(
Some(span),
closure_kind,
bound_predicate.rebind(proj_predicate),
bound_clause.rebind(proj_clause),
)),
);

Expand Down Expand Up @@ -434,11 +431,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// infer the kind. This can occur when we elaborate a predicate
// like `F : Fn<A>`. Note that due to subtyping we could encounter
// many viable options, so pick the most restrictive.
let trait_def_id = match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
let trait_def_id = match bound_clause.skip_binder() {
ty::ClauseKind::Projection(data) => {
Some(data.projection_term.trait_def_id(self.tcx))
}
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()),
ty::ClauseKind::Trait(data) => Some(data.def_id()),
_ => None,
};

Expand Down Expand Up @@ -964,21 +961,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.resolve_vars_with_obligations(ret_ty);

let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
let get_future_output = |clause: ty::Clause<'tcx>, span| {
// Search for a pending obligation like
//
// `<R as Future>::Output = T`
//
// where R is the return type we are expecting. This type `T`
// will be our output.
let bound_predicate = predicate.kind();
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_predicate)) =
bound_predicate.skip_binder()
{
self.deduce_future_output_from_projection(
span,
bound_predicate.rebind(proj_predicate),
)
let bound_clause = clause.kind();
if let ty::ClauseKind::Projection(proj_clause) = bound_clause.skip_binder() {
self.deduce_future_output_from_projection(span, bound_clause.rebind(proj_clause))
} else {
None
}
Expand All @@ -987,7 +979,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let output_ty = match *ret_ty.kind() {
ty::Infer(ty::TyVar(ret_vid)) => {
self.obligations_for_self_ty(ret_vid).into_iter().find_map(|obligation| {
get_future_output(obligation.predicate, obligation.cause.span)
obligation
.predicate
.as_clause()
.and_then(|clause| get_future_output(clause, obligation.cause.span))
})?
}
ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
Expand All @@ -1002,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.explicit_item_self_bounds(def_id)
.iter_instantiated_copied(self.tcx, args)
.map(Unnormalized::skip_norm_wip)
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
.find_map(|(c, s)| get_future_output(c, s))?,
ty::Error(_) => return Some(ret_ty),
_ => {
span_bug!(closure_span, "invalid async fn coroutine return type: {ret_ty:?}")
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
let span = tcx.def_span(def_id);

ty::EarlyBinder::bind(tcx.arena.alloc_from_iter(
self.param_env.caller_bounds().iter().filter_map(|predicate| {
match predicate.kind().skip_binder() {
self.param_env.caller_bounds().iter().filter_map(|clause| {
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => {
Some((predicate, span))
Some((clause, span))
}
_ => None,
}
Expand Down
Loading
Loading