Don't consider TAIT normalizable to hidden ty if it would result in impossible item bounds
This commit is contained in:
parent
18a6d911ca
commit
2e8af07a8a
5 changed files with 39 additions and 13 deletions
|
@ -1065,7 +1065,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
ocx.infcx.add_item_bounds_for_hidden_type(
|
ocx.infcx.add_item_bounds_for_hidden_type(
|
||||||
opaque_type_key,
|
opaque_type_key.def_id.to_def_id(),
|
||||||
|
opaque_type_key.substs,
|
||||||
cause,
|
cause,
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty.ty,
|
hidden_ty.ty,
|
||||||
|
|
|
@ -536,7 +536,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.add_item_bounds_for_hidden_type(
|
self.add_item_bounds_for_hidden_type(
|
||||||
opaque_type_key,
|
opaque_type_key.def_id.to_def_id(),
|
||||||
|
opaque_type_key.substs,
|
||||||
cause,
|
cause,
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty,
|
hidden_ty,
|
||||||
|
@ -598,7 +599,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
|
|
||||||
pub fn add_item_bounds_for_hidden_type(
|
pub fn add_item_bounds_for_hidden_type(
|
||||||
&self,
|
&self,
|
||||||
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
|
def_id: DefId,
|
||||||
|
substs: ty::SubstsRef<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
|
@ -631,7 +633,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
// Replace all other mentions of the same opaque type with the hidden type,
|
// Replace all other mentions of the same opaque type with the hidden type,
|
||||||
// as the bounds must hold on the hidden type after all.
|
// as the bounds must hold on the hidden type after all.
|
||||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
|
||||||
if def_id.to_def_id() == def_id2 && substs == substs2 =>
|
if def_id == def_id2 && substs == substs2 =>
|
||||||
{
|
{
|
||||||
hidden_ty
|
hidden_ty
|
||||||
}
|
}
|
||||||
|
@ -640,7 +642,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
ty::Alias(
|
ty::Alias(
|
||||||
ty::Projection,
|
ty::Projection,
|
||||||
ty::AliasTy { def_id: def_id2, substs: substs2, .. },
|
ty::AliasTy { def_id: def_id2, substs: substs2, .. },
|
||||||
) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
|
) if def_id == def_id2 && substs == substs2 => hidden_ty,
|
||||||
_ => ty,
|
_ => ty,
|
||||||
},
|
},
|
||||||
lt_op: |lt| lt,
|
lt_op: |lt| lt,
|
||||||
|
|
|
@ -835,13 +835,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
pub(super) fn add_item_bounds_for_hidden_type(
|
pub(super) fn add_item_bounds_for_hidden_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
opaque_def_id: DefId,
|
||||||
|
opaque_substs: ty::SubstsRef<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
let mut obligations = Vec::new();
|
let mut obligations = Vec::new();
|
||||||
self.infcx.add_item_bounds_for_hidden_type(
|
self.infcx.add_item_bounds_for_hidden_type(
|
||||||
opaque_type_key,
|
opaque_def_id,
|
||||||
|
opaque_substs,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty,
|
hidden_ty,
|
||||||
|
@ -872,7 +874,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
ecx.eq(param_env, a, b)?;
|
ecx.eq(param_env, a, b)?;
|
||||||
}
|
}
|
||||||
ecx.eq(param_env, candidate_ty, ty)?;
|
ecx.eq(param_env, candidate_ty, ty)?;
|
||||||
ecx.add_item_bounds_for_hidden_type(candidate_key, param_env, candidate_ty);
|
ecx.add_item_bounds_for_hidden_type(
|
||||||
|
candidate_key.def_id.to_def_id(),
|
||||||
|
candidate_key.substs,
|
||||||
|
param_env,
|
||||||
|
candidate_ty,
|
||||||
|
);
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
},
|
},
|
||||||
|r| CandidateKind::Candidate { name: "opaque type storage".into(), result: *r },
|
|r| CandidateKind::Candidate { name: "opaque type storage".into(), result: *r },
|
||||||
|
|
|
@ -20,8 +20,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
|
let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
};
|
};
|
||||||
let opaque_ty =
|
|
||||||
ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
|
|
||||||
// FIXME: at some point we should call queries without defining
|
// FIXME: at some point we should call queries without defining
|
||||||
// new opaque types but having the existing opaque type definitions.
|
// new opaque types but having the existing opaque type definitions.
|
||||||
// This will require moving this below "Prefer opaques registered already".
|
// This will require moving this below "Prefer opaques registered already".
|
||||||
|
@ -41,7 +39,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
}
|
}
|
||||||
// Prefer opaques registered already.
|
// Prefer opaques registered already.
|
||||||
let matches = self.unify_existing_opaque_tys(goal.param_env, opaque_ty, expected);
|
let opaque_type_key =
|
||||||
|
ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
|
||||||
|
let matches =
|
||||||
|
self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected);
|
||||||
if !matches.is_empty() {
|
if !matches.is_empty() {
|
||||||
if let Some(response) = self.try_merge_responses(&matches) {
|
if let Some(response) = self.try_merge_responses(&matches) {
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
|
@ -50,11 +51,24 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise, define a new opaque type
|
// Otherwise, define a new opaque type
|
||||||
self.insert_hidden_type(opaque_ty, goal.param_env, expected)?;
|
self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
|
||||||
self.add_item_bounds_for_hidden_type(opaque_ty, goal.param_env, expected);
|
self.add_item_bounds_for_hidden_type(
|
||||||
|
opaque_ty.def_id,
|
||||||
|
opaque_ty.substs,
|
||||||
|
goal.param_env,
|
||||||
|
expected,
|
||||||
|
);
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
(Reveal::UserFacing, SolverMode::Coherence) => {
|
(Reveal::UserFacing, SolverMode::Coherence) => {
|
||||||
|
// An impossible opaque type bound is the only way this goal will fail
|
||||||
|
// e.g. assigning `impl Copy := NotCopy`
|
||||||
|
self.add_item_bounds_for_hidden_type(
|
||||||
|
opaque_ty.def_id,
|
||||||
|
opaque_ty.substs,
|
||||||
|
goal.param_env,
|
||||||
|
expected,
|
||||||
|
);
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||||
}
|
}
|
||||||
(Reveal::All, _) => {
|
(Reveal::All, _) => {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Regression test for issue #76202
|
// Regression test for issue #76202
|
||||||
// Tests that we don't ICE when we have a trait impl on a TAIT.
|
// Tests that we don't ICE when we have a trait impl on a TAIT.
|
||||||
|
|
||||||
|
// revisions: current next
|
||||||
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue