1
Fork 0

Make RPIT and TAIT work exactly the same

This commit is contained in:
Oli Scherer 2022-05-27 19:31:10 +00:00
parent 493c960a3e
commit 524d2b3178
57 changed files with 359 additions and 221 deletions

View file

@ -38,6 +38,15 @@ pub struct OpaqueTypeDecl<'tcx> {
pub origin: hir::OpaqueTyOrigin,
}
pub enum ReplaceOpaqueTypes {
/// Closures can't create hidden types for opaque types of their parent, as they
/// do not have all the outlives information available. Also `type_of` looks for
/// hidden types in the owner (so the closure's parent), so it would not find these
/// definitions.
OnlyForRPIT,
All,
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn replace_opaque_types_with_inference_vars(
&self,
@ -46,27 +55,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
span: Span,
code: ObligationCauseCode<'tcx>,
param_env: ty::ParamEnv<'tcx>,
replace: ReplaceOpaqueTypes,
) -> InferOk<'tcx, Ty<'tcx>> {
if !ty.has_opaque_types() {
return InferOk { value: ty, obligations: vec![] };
}
let mut obligations = vec![];
let replace_opaque_type = |def_id| match self.opaque_type_origin(def_id, span) {
None => false,
Some(OpaqueTyOrigin::FnReturn(..)) => true,
// Not using `==` or `matches!` here to make sure we exhaustively match variants.
Some(_) => match replace {
ReplaceOpaqueTypes::OnlyForRPIT => false,
ReplaceOpaqueTypes::All => true,
},
};
let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.tcx,
lt_op: |lt| lt,
ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() {
// Closures can't create hidden types for opaque types of their parent, as they
// do not have all the outlives information available. Also `type_of` looks for
// hidden types in the owner (so the closure's parent), so it would not find these
// definitions.
ty::Opaque(def_id, _substs)
if matches!(
self.opaque_type_origin(def_id, span),
Some(OpaqueTyOrigin::FnReturn(..))
) =>
{
let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span };
ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
let def_span = self.tcx.def_span(def_id);
let span = if span.contains(def_span) { def_span } else { span };
let cause = ObligationCause::new(span, body_id, code.clone());
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
// for opaque types, and then use that kind to fix the spans for type errors