More comments
This commit is contained in:
parent
f49b0dcce2
commit
3799568895
2 changed files with 30 additions and 10 deletions
|
@ -2,15 +2,29 @@
|
||||||
//! Doing this via a separate goal is called "deferred alias relation" and part
|
//! Doing this via a separate goal is called "deferred alias relation" and part
|
||||||
//! of our more general approach to "lazy normalization".
|
//! of our more general approach to "lazy normalization".
|
||||||
//!
|
//!
|
||||||
//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches:
|
//! This is done by first normalizing both sides of the goal, ending up in
|
||||||
//! * normalizes-to: If `A` is a projection, we can prove the equivalent
|
//! either a concrete type, rigid projection, opaque, or an infer variable.
|
||||||
//! projection predicate with B as the right-hand side of the projection.
|
//! These are related further according to the rules below:
|
||||||
//! This goal is computed in both directions, if both are aliases.
|
//!
|
||||||
//! * subst-relate: Equate `A` and `B` by their substs, if they're both
|
//! (1.) If we end up with a rigid projection and a rigid projection, then we
|
||||||
//! aliases with the same def-id.
|
//! relate those projections structurally.
|
||||||
//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
|
//!
|
||||||
//! may apply, then we can compute the "intersection" of both normalizes-to by
|
//! (2.) If we end up with a rigid projection and an alias, then the opaque will
|
||||||
//! performing them together. This is used specifically to resolve ambiguities.
|
//! have its hidden type defined to be that rigid projection.
|
||||||
|
//!
|
||||||
|
//! (3.) If we end up with an opaque and an opaque, then we assemble two
|
||||||
|
//! candidates, one defining the LHS to be the hidden type of the RHS, and vice
|
||||||
|
//! versa.
|
||||||
|
//!
|
||||||
|
//! (4.) If we end up with an infer var and an opaque or rigid projection, then
|
||||||
|
//! we assign the alias to the infer var.
|
||||||
|
//!
|
||||||
|
//! (5.) If we end up with an opaque and a rigid (non-projection) type, then we
|
||||||
|
//! define the hidden type of the opaque to be the rigid type.
|
||||||
|
//!
|
||||||
|
//! (6.) Otherwise, if we end with two rigid (non-projection) or infer types,
|
||||||
|
//! relate them structurally.
|
||||||
|
|
||||||
use super::{EvalCtxt, GoalSource};
|
use super::{EvalCtxt, GoalSource};
|
||||||
use rustc_infer::infer::DefineOpaqueTypes;
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
|
@ -50,6 +64,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
self.relate(param_env, lhs, variance, rhs)?;
|
self.relate(param_env, lhs, variance, rhs)?;
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
} else if alias.is_opaque(tcx) {
|
} else if alias.is_opaque(tcx) {
|
||||||
|
// FIXME: This doesn't account for variance.
|
||||||
self.define_opaque(param_env, alias, rhs)
|
self.define_opaque(param_env, alias, rhs)
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
|
@ -60,6 +75,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
self.relate(param_env, lhs, variance, rhs)?;
|
self.relate(param_env, lhs, variance, rhs)?;
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
} else if alias.is_opaque(tcx) {
|
} else if alias.is_opaque(tcx) {
|
||||||
|
// FIXME: This doesn't account for variance.
|
||||||
self.define_opaque(param_env, alias, lhs)
|
self.define_opaque(param_env, alias, lhs)
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
|
@ -72,6 +88,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This needs a name that reflects that it's okay to bottom-out with an inference var.
|
||||||
/// Normalize the `term` to equate it later. This does not define opaque types.
|
/// Normalize the `term` to equate it later. This does not define opaque types.
|
||||||
#[instrument(level = "debug", skip(self, param_env), ret)]
|
#[instrument(level = "debug", skip(self, param_env), ret)]
|
||||||
fn try_normalize_term(
|
fn try_normalize_term(
|
||||||
|
|
|
@ -317,7 +317,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
};
|
};
|
||||||
|
|
||||||
// We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
|
// We do no always define opaque types eagerly to allow non-defining uses
|
||||||
|
// in the defining scope. However, if we can unify this opaque to an existing
|
||||||
|
// opaque, then we should attempt to eagerly reveal the opaque, and we fall
|
||||||
|
// through.
|
||||||
if let DefineOpaqueTypes::No = define_opaque_types
|
if let DefineOpaqueTypes::No = define_opaque_types
|
||||||
&& let Reveal::UserFacing = param_env.reveal()
|
&& let Reveal::UserFacing = param_env.reveal()
|
||||||
&& let ty::Opaque = kind
|
&& let ty::Opaque = kind
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue