Check hidden types for well formedness at the definition site instead of only at the opaque type itself
This commit is contained in:
parent
12d3f107c1
commit
f667e952f8
32 changed files with 311 additions and 150 deletions
|
@ -1,11 +1,15 @@
|
|||
use crate::traits;
|
||||
use crate::traits::error_reporting::InferCtxtExt as _;
|
||||
use crate::traits::TraitEngineExt as _;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _};
|
||||
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub trait InferCtxtExt<'tcx> {
|
||||
|
@ -13,6 +17,7 @@ pub trait InferCtxtExt<'tcx> {
|
|||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
|
@ -45,6 +50,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Ty<'tcx> {
|
||||
if self.is_tainted_by_errors() {
|
||||
return self.tcx.ty_error();
|
||||
|
@ -76,7 +82,69 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
));
|
||||
debug!(?definition_ty);
|
||||
|
||||
definition_ty
|
||||
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
|
||||
// on stable and we'd break that.
|
||||
if let OpaqueTyOrigin::TyAlias = origin {
|
||||
// This logic duplicates most of `check_opaque_meets_bounds`.
|
||||
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
|
||||
let param_env = self.tcx.param_env(def_id);
|
||||
let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap());
|
||||
self.tcx.infer_ctxt().enter(move |infcx| {
|
||||
// Require the hidden type to be well-formed with only the generics of the opaque type.
|
||||
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
|
||||
// hidden type is well formed even without those bounds.
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
|
||||
.to_predicate(infcx.tcx);
|
||||
let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
|
||||
|
||||
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
|
||||
// the bounds that the function supplies.
|
||||
match infcx.register_hidden_type(
|
||||
OpaqueTypeKey { def_id, substs: id_substs },
|
||||
ObligationCause::misc(instantiated_ty.span, body_id),
|
||||
param_env,
|
||||
definition_ty,
|
||||
origin,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
for obligation in infer_ok.obligations {
|
||||
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
infcx
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(instantiated_ty.span, body_id),
|
||||
self.tcx.mk_opaque(def_id, id_substs),
|
||||
definition_ty,
|
||||
err,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fulfillment_cx.register_predicate_obligation(
|
||||
&infcx,
|
||||
Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
|
||||
);
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
||||
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
|
||||
if errors.is_empty() {
|
||||
definition_ty
|
||||
} else {
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
self.tcx.ty_error()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
definition_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue