rework alias-relate to norm(lhs) == norm(rhs)
This commit is contained in:
parent
1c54494888
commit
e3850f404d
@ -1245,6 +1245,28 @@ pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this alias type is an opaque.
|
||||||
|
pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||||
|
matches!(self.opt_kind(tcx), Some(ty::AliasKind::Opaque))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FIXME: rename `AliasTy` to `AliasTerm` and always handle
|
||||||
|
/// constants. This function can then be removed.
|
||||||
|
pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option<ty::AliasKind> {
|
||||||
|
match tcx.def_kind(self.def_id) {
|
||||||
|
DefKind::AssocTy
|
||||||
|
if let DefKind::Impl { of_trait: false } =
|
||||||
|
tcx.def_kind(tcx.parent(self.def_id)) =>
|
||||||
|
{
|
||||||
|
Some(ty::Inherent)
|
||||||
|
}
|
||||||
|
DefKind::AssocTy => Some(ty::Projection),
|
||||||
|
DefKind::OpaqueTy => Some(ty::Opaque),
|
||||||
|
DefKind::TyAlias => Some(ty::Weak),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
Ty::new_alias(tcx, self.kind(tcx), self)
|
Ty::new_alias(tcx, self.kind(tcx), self)
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,12 @@
|
|||||||
//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
|
//! * 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
|
//! may apply, then we can compute the "intersection" of both normalizes-to by
|
||||||
//! performing them together. This is used specifically to resolve ambiguities.
|
//! performing them together. This is used specifically to resolve ambiguities.
|
||||||
use super::{EvalCtxt, SolverMode};
|
use super::EvalCtxt;
|
||||||
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
/// We may need to invert the alias relation direction if dealing an alias on the RHS.
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Invert {
|
|
||||||
No,
|
|
||||||
Yes,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub(super) fn compute_alias_relate_goal(
|
pub(super) fn compute_alias_relate_goal(
|
||||||
@ -31,187 +25,130 @@ pub(super) fn compute_alias_relate_goal(
|
|||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
|
let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
|
||||||
if lhs.is_infer() || rhs.is_infer() {
|
|
||||||
bug!(
|
let Some(lhs) = self.try_normalize_term(param_env, lhs)? else {
|
||||||
"`AliasRelate` goal with an infer var on lhs or rhs which should have been instantiated"
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(rhs) = self.try_normalize_term(param_env, rhs)? else {
|
||||||
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
|
||||||
|
};
|
||||||
|
|
||||||
|
let variance = match direction {
|
||||||
|
ty::AliasRelationDirection::Equate => ty::Variance::Invariant,
|
||||||
|
ty::AliasRelationDirection::Subtype => ty::Variance::Covariant,
|
||||||
|
};
|
||||||
|
|
||||||
|
match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
|
||||||
|
(None, None) => {
|
||||||
|
self.relate(param_env, lhs, variance, rhs)?;
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
}
|
||||||
|
|
||||||
|
(Some(alias), None) => {
|
||||||
|
if rhs.is_infer() {
|
||||||
|
self.relate(param_env, lhs, variance, rhs)?;
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
} else if alias.is_opaque(tcx) {
|
||||||
|
self.define_opaque(param_env, alias, rhs)
|
||||||
|
} else {
|
||||||
|
Err(NoSolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(None, Some(alias)) => {
|
||||||
|
if lhs.is_infer() {
|
||||||
|
self.relate(param_env, lhs, variance, rhs)?;
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
} else if alias.is_opaque(tcx) {
|
||||||
|
self.define_opaque(param_env, alias, lhs)
|
||||||
|
} else {
|
||||||
|
Err(NoSolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(Some(alias_lhs), Some(alias_rhs)) => {
|
||||||
|
self.relate_rigid_alias_or_opaque(param_env, alias_lhs, variance, alias_rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Normalize the `term` to equate it later. This does not define opaque types.
|
||||||
|
#[instrument(level = "debug", skip(self, param_env), ret)]
|
||||||
|
fn try_normalize_term(
|
||||||
|
&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
term: ty::Term<'tcx>,
|
||||||
|
) -> Result<Option<ty::Term<'tcx>>, NoSolution> {
|
||||||
|
match term.unpack() {
|
||||||
|
ty::TermKind::Ty(ty) => {
|
||||||
|
// We do no define opaque types here but instead do so in `relate_rigid_alias_or_opaque`.
|
||||||
|
Ok(self
|
||||||
|
.try_normalize_ty_recur(param_env, DefineOpaqueTypes::No, 0, ty)
|
||||||
|
.map(Into::into))
|
||||||
|
}
|
||||||
|
ty::TermKind::Const(_) => {
|
||||||
|
if let Some(alias) = term.to_alias_ty(self.tcx()) {
|
||||||
|
let term = self.next_term_infer_of_kind(term);
|
||||||
|
self.add_goal(Goal::new(
|
||||||
|
self.tcx(),
|
||||||
|
param_env,
|
||||||
|
ty::ProjectionPredicate { projection_ty: alias, term },
|
||||||
|
));
|
||||||
|
self.try_evaluate_added_goals()?;
|
||||||
|
Ok(Some(self.resolve_vars_if_possible(term)))
|
||||||
|
} else {
|
||||||
|
Ok(Some(term))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_opaque(
|
||||||
|
&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
opaque: ty::AliasTy<'tcx>,
|
||||||
|
term: ty::Term<'tcx>,
|
||||||
|
) -> QueryResult<'tcx> {
|
||||||
|
self.add_goal(Goal::new(
|
||||||
|
self.tcx(),
|
||||||
|
param_env,
|
||||||
|
ty::ProjectionPredicate { projection_ty: opaque, term },
|
||||||
|
));
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn relate_rigid_alias_or_opaque(
|
||||||
|
&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
lhs: ty::AliasTy<'tcx>,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: ty::AliasTy<'tcx>,
|
||||||
|
) -> QueryResult<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
let mut candidates = vec![];
|
||||||
|
if lhs.is_opaque(tcx) {
|
||||||
|
candidates.extend(
|
||||||
|
self.probe_misc_candidate("define-lhs-opaque")
|
||||||
|
.enter(|ecx| ecx.define_opaque(param_env, lhs, rhs.to_ty(tcx).into())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
|
if rhs.is_opaque(tcx) {
|
||||||
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
|
|
||||||
|
|
||||||
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS
|
|
||||||
(Some(alias_lhs), None) => self.assemble_normalizes_to_candidate(
|
|
||||||
param_env,
|
|
||||||
alias_lhs,
|
|
||||||
rhs,
|
|
||||||
direction,
|
|
||||||
Invert::No,
|
|
||||||
),
|
|
||||||
|
|
||||||
// LHS is not a projection, only way this is true is if RHS normalizes-to LHS
|
|
||||||
(None, Some(alias_rhs)) => self.assemble_normalizes_to_candidate(
|
|
||||||
param_env,
|
|
||||||
alias_rhs,
|
|
||||||
lhs,
|
|
||||||
direction,
|
|
||||||
Invert::Yes,
|
|
||||||
),
|
|
||||||
|
|
||||||
(Some(alias_lhs), Some(alias_rhs)) => {
|
|
||||||
debug!("both sides are aliases");
|
|
||||||
|
|
||||||
let mut candidates = Vec::new();
|
|
||||||
// LHS normalizes-to RHS
|
|
||||||
candidates.extend(self.assemble_normalizes_to_candidate(
|
|
||||||
param_env,
|
|
||||||
alias_lhs,
|
|
||||||
rhs,
|
|
||||||
direction,
|
|
||||||
Invert::No,
|
|
||||||
));
|
|
||||||
// RHS normalizes-to RHS
|
|
||||||
candidates.extend(self.assemble_normalizes_to_candidate(
|
|
||||||
param_env,
|
|
||||||
alias_rhs,
|
|
||||||
lhs,
|
|
||||||
direction,
|
|
||||||
Invert::Yes,
|
|
||||||
));
|
|
||||||
// Relate via args
|
|
||||||
candidates.extend(
|
candidates.extend(
|
||||||
self.assemble_subst_relate_candidate(
|
self.probe_misc_candidate("define-rhs-opaque")
|
||||||
param_env, alias_lhs, alias_rhs, direction,
|
.enter(|ecx| ecx.define_opaque(param_env, rhs, lhs.to_ty(tcx).into())),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
debug!(?candidates);
|
}
|
||||||
|
|
||||||
if let Some(merged) = self.try_merge_responses(&candidates) {
|
candidates.extend(self.probe_misc_candidate("args-relate").enter(|ecx| {
|
||||||
Ok(merged)
|
ecx.relate(param_env, lhs, variance, rhs)?;
|
||||||
} else {
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
// When relating two aliases and we have ambiguity, if both
|
}));
|
||||||
// aliases can be normalized to something, we prefer
|
|
||||||
// "bidirectionally normalizing" both of them within the same
|
if let Some(result) = self.try_merge_responses(&candidates) {
|
||||||
// candidate.
|
Ok(result)
|
||||||
//
|
|
||||||
// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/25>.
|
|
||||||
//
|
|
||||||
// As this is incomplete, we must not do so during coherence.
|
|
||||||
match self.solver_mode() {
|
|
||||||
SolverMode::Normal => {
|
|
||||||
if let Ok(bidirectional_normalizes_to_response) = self
|
|
||||||
.assemble_bidirectional_normalizes_to_candidate(
|
|
||||||
param_env, lhs, rhs, direction,
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Ok(bidirectional_normalizes_to_response)
|
|
||||||
} else {
|
} else {
|
||||||
self.flounder(&candidates)
|
self.flounder(&candidates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SolverMode::Coherence => self.flounder(&candidates),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
|
||||||
fn assemble_normalizes_to_candidate(
|
|
||||||
&mut self,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
alias: ty::AliasTy<'tcx>,
|
|
||||||
other: ty::Term<'tcx>,
|
|
||||||
direction: ty::AliasRelationDirection,
|
|
||||||
invert: Invert,
|
|
||||||
) -> QueryResult<'tcx> {
|
|
||||||
self.probe_misc_candidate("normalizes-to").enter(|ecx| {
|
|
||||||
ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?;
|
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Computes the normalizes-to branch, with side-effects. This must be performed
|
|
||||||
// in a probe in order to not taint the evaluation context.
|
|
||||||
fn normalizes_to_inner(
|
|
||||||
&mut self,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
alias: ty::AliasTy<'tcx>,
|
|
||||||
other: ty::Term<'tcx>,
|
|
||||||
direction: ty::AliasRelationDirection,
|
|
||||||
invert: Invert,
|
|
||||||
) -> Result<(), NoSolution> {
|
|
||||||
let other = match direction {
|
|
||||||
// This is purely an optimization. No need to instantiate a new
|
|
||||||
// infer var and equate the RHS to it.
|
|
||||||
ty::AliasRelationDirection::Equate => other,
|
|
||||||
|
|
||||||
// Instantiate an infer var and subtype our RHS to it, so that we
|
|
||||||
// properly represent a subtype relation between the LHS and RHS
|
|
||||||
// of the goal.
|
|
||||||
ty::AliasRelationDirection::Subtype => {
|
|
||||||
let fresh = self.next_term_infer_of_kind(other);
|
|
||||||
let (sub, sup) = match invert {
|
|
||||||
Invert::No => (fresh, other),
|
|
||||||
Invert::Yes => (other, fresh),
|
|
||||||
};
|
|
||||||
self.sub(param_env, sub, sup)?;
|
|
||||||
fresh
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.add_goal(Goal::new(
|
|
||||||
self.tcx(),
|
|
||||||
param_env,
|
|
||||||
ty::ProjectionPredicate { projection_ty: alias, term: other },
|
|
||||||
));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_subst_relate_candidate(
|
|
||||||
&mut self,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
alias_lhs: ty::AliasTy<'tcx>,
|
|
||||||
alias_rhs: ty::AliasTy<'tcx>,
|
|
||||||
direction: ty::AliasRelationDirection,
|
|
||||||
) -> QueryResult<'tcx> {
|
|
||||||
self.probe_misc_candidate("args relate").enter(|ecx| {
|
|
||||||
match direction {
|
|
||||||
ty::AliasRelationDirection::Equate => {
|
|
||||||
ecx.eq(param_env, alias_lhs, alias_rhs)?;
|
|
||||||
}
|
|
||||||
ty::AliasRelationDirection::Subtype => {
|
|
||||||
ecx.sub(param_env, alias_lhs, alias_rhs)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_bidirectional_normalizes_to_candidate(
|
|
||||||
&mut self,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
lhs: ty::Term<'tcx>,
|
|
||||||
rhs: ty::Term<'tcx>,
|
|
||||||
direction: ty::AliasRelationDirection,
|
|
||||||
) -> QueryResult<'tcx> {
|
|
||||||
self.probe_misc_candidate("bidir normalizes-to").enter(|ecx| {
|
|
||||||
ecx.normalizes_to_inner(
|
|
||||||
param_env,
|
|
||||||
lhs.to_alias_ty(ecx.tcx()).unwrap(),
|
|
||||||
rhs,
|
|
||||||
direction,
|
|
||||||
Invert::No,
|
|
||||||
)?;
|
|
||||||
ecx.normalizes_to_inner(
|
|
||||||
param_env,
|
|
||||||
rhs.to_alias_ty(ecx.tcx()).unwrap(),
|
|
||||||
lhs,
|
|
||||||
direction,
|
|
||||||
Invert::Yes,
|
|
||||||
)?;
|
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -751,6 +751,26 @@ pub(super) fn sub<T: ToTrace<'tcx>>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self, param_env), ret)]
|
||||||
|
pub(super) fn relate<T: ToTrace<'tcx>>(
|
||||||
|
&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
lhs: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<(), NoSolution> {
|
||||||
|
self.infcx
|
||||||
|
.at(&ObligationCause::dummy(), param_env)
|
||||||
|
.relate(DefineOpaqueTypes::No, lhs, variance, rhs)
|
||||||
|
.map(|InferOk { value: (), obligations }| {
|
||||||
|
self.add_goals(obligations.into_iter().map(|o| o.into()));
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
debug!(?e, "failed to relate");
|
||||||
|
NoSolution
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Equates two values returning the nested goals without adding them
|
/// Equates two values returning the nested goals without adding them
|
||||||
/// to the nested goals of the `EvalCtxt`.
|
/// to the nested goals of the `EvalCtxt`.
|
||||||
///
|
///
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
//! about it on zulip.
|
//! about it on zulip.
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_middle::infer::canonical::CanonicalVarInfos;
|
use rustc_middle::infer::canonical::CanonicalVarInfos;
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{
|
||||||
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, IsNormalizesToHack, QueryResult,
|
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, IsNormalizesToHack, QueryResult,
|
||||||
Response,
|
Response,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
|
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
|
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
|
||||||
};
|
};
|
||||||
@ -299,12 +300,13 @@ fn try_normalize_ty(
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Option<Ty<'tcx>> {
|
) -> Option<Ty<'tcx>> {
|
||||||
self.try_normalize_ty_recur(param_env, 0, ty)
|
self.try_normalize_ty_recur(param_env, DefineOpaqueTypes::Yes, 0, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_normalize_ty_recur(
|
fn try_normalize_ty_recur(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
define_opaque_types: DefineOpaqueTypes,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Option<Ty<'tcx>> {
|
) -> Option<Ty<'tcx>> {
|
||||||
@ -312,10 +314,26 @@ fn try_normalize_ty_recur(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty::Alias(_, projection_ty) = *ty.kind() else {
|
let ty::Alias(kind, projection_ty) = *ty.kind() else {
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
|
||||||
|
if let (DefineOpaqueTypes::No, ty::AliasKind::Opaque) = (define_opaque_types, kind) {
|
||||||
|
if let Some(def_id) = projection_ty.def_id.as_local() {
|
||||||
|
if self
|
||||||
|
.unify_existing_opaque_tys(
|
||||||
|
param_env,
|
||||||
|
OpaqueTypeKey { def_id, args: projection_ty.args },
|
||||||
|
self.next_ty_infer(),
|
||||||
|
)
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
return Some(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(@lcnr): If the normalization of the alias adds an inference constraint which
|
// FIXME(@lcnr): If the normalization of the alias adds an inference constraint which
|
||||||
// causes a previously added goal to fail, then we treat the alias as rigid.
|
// causes a previously added goal to fail, then we treat the alias as rigid.
|
||||||
//
|
//
|
||||||
@ -331,7 +349,7 @@ fn try_normalize_ty_recur(
|
|||||||
this.add_goal(normalizes_to_goal);
|
this.add_goal(normalizes_to_goal);
|
||||||
this.try_evaluate_added_goals()?;
|
this.try_evaluate_added_goals()?;
|
||||||
let ty = this.resolve_vars_if_possible(normalized_ty);
|
let ty = this.resolve_vars_if_possible(normalized_ty);
|
||||||
Ok(this.try_normalize_ty_recur(param_env, depth + 1, ty))
|
Ok(this.try_normalize_ty_recur(param_env, define_opaque_types, depth + 1, ty))
|
||||||
}) {
|
}) {
|
||||||
Ok(ty) => ty,
|
Ok(ty) => ty,
|
||||||
Err(NoSolution) => Some(ty),
|
Err(NoSolution) => Some(ty),
|
||||||
|
Loading…
Reference in New Issue
Block a user