1
Fork 0

Don't consider TAIT normalizable to hidden ty if it would result in impossible item bounds

This commit is contained in:
Michael Goulet 2023-06-18 23:11:22 +00:00
parent 18a6d911ca
commit 2e8af07a8a
5 changed files with 39 additions and 13 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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 },

View file

@ -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, _) => {

View file

@ -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)]