Add some extra information to opaque type cycle errors
This commit is contained in:
parent
66ae9998d5
commit
9e98feb84c
16 changed files with 421 additions and 24 deletions
|
@ -30,7 +30,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
|||
use rustc_infer::infer::{InferOk, TypeTrace};
|
||||
use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::traits::solve::Goal;
|
||||
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
|
||||
use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
|
@ -1152,6 +1152,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
|
||||
&obligation,
|
||||
def_id,
|
||||
),
|
||||
|
||||
TraitNotObjectSafe(did) => {
|
||||
let violations = self.tcx.object_safety_violations(did);
|
||||
report_object_safety_error(self.tcx, span, did, violations)
|
||||
|
@ -1465,6 +1470,12 @@ trait InferCtxtPrivExt<'tcx> {
|
|||
terr: TypeError<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
fn report_opaque_type_auto_trait_leakage(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
def_id: DefId,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
fn report_type_parameter_mismatch_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
|
@ -3186,6 +3197,39 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn report_opaque_type_auto_trait_leakage(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
def_id: DefId,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
|
||||
hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
|
||||
format!("opaque type")
|
||||
}
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||
format!("`{}`", self.tcx.def_path_debug_str(def_id))
|
||||
}
|
||||
};
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
obligation.cause.span,
|
||||
format!("cannot check whether the hidden type of {name} satisfies auto traits"),
|
||||
);
|
||||
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
|
||||
match self.defining_use_anchor {
|
||||
DefiningAnchor::Bubble | DefiningAnchor::Error => {}
|
||||
DefiningAnchor::Bind(bind) => {
|
||||
err.span_note(
|
||||
self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
|
||||
"this item depends on auto traits of the hidden type, \
|
||||
but may also be registering the hidden type. \
|
||||
This is not supported right now. \
|
||||
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
|
||||
);
|
||||
}
|
||||
};
|
||||
err
|
||||
}
|
||||
|
||||
fn report_type_parameter_mismatch_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
|
|
|
@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
AutoImplCandidate => {
|
||||
let data = self.confirm_auto_impl_candidate(obligation);
|
||||
let data = self.confirm_auto_impl_candidate(obligation)?;
|
||||
ImplSource::Builtin(data)
|
||||
}
|
||||
|
||||
|
@ -376,12 +376,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn confirm_auto_impl_candidate(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
) -> Vec<PredicateObligation<'tcx>> {
|
||||
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||
debug!(?obligation, "confirm_auto_impl_candidate");
|
||||
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
|
||||
let types = self.constituent_types_for_ty(self_ty);
|
||||
self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
|
||||
let types = self.constituent_types_for_ty(self_ty)?;
|
||||
Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
|
||||
}
|
||||
|
||||
/// See `confirm_auto_impl_candidate`.
|
||||
|
|
|
@ -2294,8 +2294,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
fn constituent_types_for_ty(
|
||||
&self,
|
||||
t: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
||||
match *t.skip_binder().kind() {
|
||||
) -> Result<ty::Binder<'tcx, Vec<Ty<'tcx>>>, SelectionError<'tcx>> {
|
||||
Ok(match *t.skip_binder().kind() {
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
| ty::Bool
|
||||
|
@ -2359,12 +2359,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
}
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
let ty = self.tcx().type_of(def_id);
|
||||
if ty.skip_binder().references_error() {
|
||||
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
|
||||
}
|
||||
// We can resolve the `impl Trait` to its concrete type,
|
||||
// which enforces a DAG between the functions requiring
|
||||
// the auto trait bounds in question.
|
||||
t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
|
||||
t.rebind(vec![ty.subst(self.tcx(), substs)])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn collect_predicates_for_types(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue