Merge two duplicates of the same logic into a common function

This commit is contained in:
Oli Scherer 2022-02-17 14:49:45 +00:00
parent 2bf63a5011
commit 7f933de194
3 changed files with 56 additions and 76 deletions

View File

@ -1,7 +1,7 @@
use crate::infer::{InferCtxt, InferOk};
use crate::traits;
use hir::def_id::{DefId, LocalDefId};
use hir::OpaqueTyOrigin;
use hir::{HirId, OpaqueTyOrigin};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
@ -21,6 +21,7 @@ mod table;
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::InferResult;
/// Information about the opaque types whose values we
@ -38,6 +39,48 @@ pub struct OpaqueTypeDecl<'tcx> {
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn replace_opaque_types_with_inference_vars(
&self,
ty: Ty<'tcx>,
body_id: HirId,
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, Ty<'tcx>> {
let mut obligations = vec![];
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 };
let cause = ObligationCause::misc(span, body_id);
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: cause.span,
});
obligations.extend(
self.handle_opaque_type(ty, ty_var, true, &cause, param_env)
.unwrap()
.obligations,
);
ty_var
}
_ => ty,
},
});
InferOk { value, obligations }
}
pub fn handle_opaque_type(
&self,
a: Ty<'tcx>,

View File

@ -3,7 +3,6 @@ use super::compare_method::check_type_bounds;
use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
use super::*;
use hir::OpaqueTyOrigin;
use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed};
use rustc_hir as hir;
@ -13,9 +12,8 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{def::Res, ItemKind, Node, PathSegment};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
@ -97,45 +95,13 @@ pub(super) fn check_fn<'a, 'tcx>(
let declared_ret_ty = fn_sig.output();
let ret_ty = declared_ret_ty.fold_with(&mut BottomUpFolder {
tcx: fcx.tcx,
ty_op: |ty| match *ty.kind() {
ty::Opaque(def_id, substs) => {
let span = tcx.def_span(def_id);
if let Some(origin @ OpaqueTyOrigin::FnReturn(_)) =
fcx.infcx.opaque_type_origin(def_id, span)
{
let hidden_ty = fcx.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: span,
});
let cause = ObligationCause::misc(span, body.value.hir_id);
match fcx.infcx.register_hidden_type(
ty::OpaqueTypeKey { def_id, substs },
cause.clone(),
param_env,
hidden_ty,
origin,
) {
Ok(infer_ok) => {
fcx.register_infer_ok_obligations(infer_ok);
hidden_ty
}
Err(err) => {
fcx.report_mismatched_types(&cause, ty, hidden_ty, err).emit();
tcx.ty_error()
}
}
} else {
ty
}
}
_ => ty,
},
lt_op: |lt| lt,
ct_op: |ct| ct,
});
let ret_ty =
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
declared_ret_ty,
body.value.hir_id,
DUMMY_SP,
param_env,
));
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
fcx.ret_type_span = Some(decl.output.span());

View File

@ -4,14 +4,12 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use crate::astconv::AstConv;
use crate::rustc_middle::ty::subst::Subst;
use hir::OpaqueTyOrigin;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty};
@ -641,37 +639,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.infcx.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.infcx.opaque_type_origin(def_id, DUMMY_SP),
Some(OpaqueTyOrigin::FnReturn(..))
) =>
{
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
});
let cause = ObligationCause::misc(span, body_id);
self.register_predicates(
self.infcx
.handle_opaque_type(ty, ty_var, true, &cause, self.param_env)
.unwrap()
.obligations,
);
ty_var
}
_ => ty,
},
})
let InferOk { value, obligations } =
self.replace_opaque_types_with_inference_vars(ty, body_id, span, self.param_env);
self.register_predicates(obligations);
value
}
/// Invoked when we are translating the generator that results