2023-07-24 08:37:40 -07:00
|
|
|
//! Implements the `AliasRelate` goal, which is used when unifying aliases.
|
|
|
|
|
//! Doing this via a separate goal is called "deferred alias relation" and part
|
|
|
|
|
//! of our more general approach to "lazy normalization".
|
2023-07-23 12:30:52 -07:00
|
|
|
//!
|
2024-04-02 15:12:20 +02:00
|
|
|
//! This is done by first structurally normalizing both sides of the goal, ending
|
|
|
|
|
//! up in either a concrete type, rigid alias, or an infer variable.
|
2024-01-10 16:22:26 +00:00
|
|
|
//! These are related further according to the rules below:
|
|
|
|
|
//!
|
2024-01-29 17:09:17 +01:00
|
|
|
//! (1.) If we end up with two rigid aliases, then we relate them structurally.
|
2024-01-10 16:22:26 +00:00
|
|
|
//!
|
2024-02-26 10:17:43 +01:00
|
|
|
//! (2.) If we end up with an infer var and a rigid alias, then we instantiate
|
|
|
|
|
//! the infer var with the constructor of the alias and then recursively relate
|
|
|
|
|
//! the terms.
|
2024-01-10 16:22:26 +00:00
|
|
|
//!
|
2024-01-29 17:09:17 +01:00
|
|
|
//! (3.) Otherwise, if we end with two rigid (non-projection) or infer types,
|
2024-01-10 16:22:26 +00:00
|
|
|
//! relate them structurally.
|
|
|
|
|
|
2024-06-17 17:59:08 -04:00
|
|
|
use rustc_type_ir::inherent::*;
|
2025-04-24 02:32:52 +00:00
|
|
|
use rustc_type_ir::solve::GoalSource;
|
2024-06-17 17:59:08 -04:00
|
|
|
use rustc_type_ir::{self as ty, Interner};
|
2024-06-17 19:12:23 -04:00
|
|
|
use tracing::{instrument, trace};
|
2023-05-27 19:05:09 +00:00
|
|
|
|
2024-06-18 19:13:54 -04:00
|
|
|
use crate::delegate::SolverDelegate;
|
2024-06-17 17:59:08 -04:00
|
|
|
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
|
|
|
|
|
|
2024-06-18 19:13:54 -04:00
|
|
|
impl<D, I> EvalCtxt<'_, D>
|
2024-06-17 17:59:08 -04:00
|
|
|
where
|
2024-06-18 19:13:54 -04:00
|
|
|
D: SolverDelegate<Interner = I>,
|
2024-06-17 17:59:08 -04:00
|
|
|
I: Interner,
|
|
|
|
|
{
|
2024-05-12 03:29:50 +00:00
|
|
|
#[instrument(level = "trace", skip(self), ret)]
|
2023-05-27 19:05:09 +00:00
|
|
|
pub(super) fn compute_alias_relate_goal(
|
|
|
|
|
&mut self,
|
2024-06-17 17:59:08 -04:00
|
|
|
goal: Goal<I, (I::Term, I::Term, ty::AliasRelationDirection)>,
|
|
|
|
|
) -> QueryResult<I> {
|
2024-06-21 12:39:55 -04:00
|
|
|
let cx = self.cx();
|
2023-05-27 19:05:09 +00:00
|
|
|
let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
|
2025-02-18 10:29:16 +01:00
|
|
|
|
|
|
|
|
// Check that the alias-relate goal is reasonable. Writeback for
|
|
|
|
|
// `coroutine_stalled_predicates` can replace alias terms with
|
|
|
|
|
// `{type error}` if the alias still contains infer vars, so we also
|
|
|
|
|
// accept alias-relate goals where one of the terms is an error.
|
|
|
|
|
debug_assert!(
|
|
|
|
|
lhs.to_alias_term().is_some()
|
|
|
|
|
|| rhs.to_alias_term().is_some()
|
|
|
|
|
|| lhs.is_error()
|
|
|
|
|
|| rhs.is_error()
|
|
|
|
|
);
|
2023-05-27 19:05:09 +00:00
|
|
|
|
2024-04-02 15:12:20 +02:00
|
|
|
// Structurally normalize the lhs.
|
2024-05-13 10:00:38 -04:00
|
|
|
let lhs = if let Some(alias) = lhs.to_alias_term() {
|
2024-04-02 15:12:20 +02:00
|
|
|
let term = self.next_term_infer_of_kind(lhs);
|
2025-04-24 02:32:52 +00:00
|
|
|
self.add_goal(
|
|
|
|
|
GoalSource::TypeRelating,
|
|
|
|
|
goal.with(cx, ty::NormalizesTo { alias, term }),
|
|
|
|
|
);
|
2024-04-02 15:12:20 +02:00
|
|
|
term
|
|
|
|
|
} else {
|
|
|
|
|
lhs
|
2023-11-09 11:06:48 +01:00
|
|
|
};
|
2023-05-27 19:05:09 +00:00
|
|
|
|
2024-04-02 15:12:20 +02:00
|
|
|
// Structurally normalize the rhs.
|
2024-05-13 10:00:38 -04:00
|
|
|
let rhs = if let Some(alias) = rhs.to_alias_term() {
|
2024-04-02 15:12:20 +02:00
|
|
|
let term = self.next_term_infer_of_kind(rhs);
|
2025-04-24 02:32:52 +00:00
|
|
|
self.add_goal(
|
|
|
|
|
GoalSource::TypeRelating,
|
|
|
|
|
goal.with(cx, ty::NormalizesTo { alias, term }),
|
|
|
|
|
);
|
2024-04-02 15:12:20 +02:00
|
|
|
term
|
|
|
|
|
} else {
|
|
|
|
|
rhs
|
2023-11-09 11:06:48 +01:00
|
|
|
};
|
2023-05-27 19:05:09 +00:00
|
|
|
|
2024-05-28 14:50:22 -04:00
|
|
|
// Add a `make_canonical_response` probe step so that we treat this as
|
|
|
|
|
// a candidate, even if `try_evaluate_added_goals` bails due to an error.
|
|
|
|
|
// It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
|
|
|
|
|
// since equating the normalized terms will lead to additional constraints.
|
|
|
|
|
self.inspect.make_canonical_response(Certainty::AMBIGUOUS);
|
|
|
|
|
|
2024-04-02 15:12:20 +02:00
|
|
|
// Apply the constraints.
|
|
|
|
|
self.try_evaluate_added_goals()?;
|
|
|
|
|
let lhs = self.resolve_vars_if_possible(lhs);
|
|
|
|
|
let rhs = self.resolve_vars_if_possible(rhs);
|
2024-05-12 03:29:50 +00:00
|
|
|
trace!(?lhs, ?rhs);
|
2024-04-02 15:12:20 +02:00
|
|
|
|
2023-11-09 11:06:48 +01:00
|
|
|
let variance = match direction {
|
2024-06-12 15:36:35 -04:00
|
|
|
ty::AliasRelationDirection::Equate => ty::Invariant,
|
|
|
|
|
ty::AliasRelationDirection::Subtype => ty::Covariant,
|
2023-11-09 11:06:48 +01:00
|
|
|
};
|
2024-05-13 10:00:38 -04:00
|
|
|
match (lhs.to_alias_term(), rhs.to_alias_term()) {
|
2023-11-09 11:06:48 +01:00
|
|
|
(None, None) => {
|
|
|
|
|
self.relate(param_env, lhs, variance, rhs)?;
|
|
|
|
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
|
|
|
}
|
2023-05-27 19:05:09 +00:00
|
|
|
|
2024-02-26 10:17:43 +01:00
|
|
|
(Some(alias), None) => {
|
2024-04-02 15:12:20 +02:00
|
|
|
self.relate_rigid_alias_non_alias(param_env, alias, variance, rhs)?;
|
|
|
|
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
|
|
|
}
|
|
|
|
|
(None, Some(alias)) => {
|
|
|
|
|
self.relate_rigid_alias_non_alias(
|
|
|
|
|
param_env,
|
|
|
|
|
alias,
|
2024-06-12 15:36:35 -04:00
|
|
|
variance.xform(ty::Contravariant),
|
2024-04-02 15:12:20 +02:00
|
|
|
lhs,
|
|
|
|
|
)?;
|
|
|
|
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
2023-11-09 11:06:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(Some(alias_lhs), Some(alias_rhs)) => {
|
2024-01-29 17:09:17 +01:00
|
|
|
self.relate(param_env, alias_lhs, variance, alias_rhs)?;
|
|
|
|
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
2023-11-09 11:06:48 +01:00
|
|
|
}
|
2023-05-27 19:05:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|