Rollup merge of #99383 - ouz-a:issue_57961, r=oli-obk
Formalize defining_use_anchor This tackles issue #57961 Introduces new enum called `DefiningAnchor` that replaces `Option<LocalDefId>` of `defining_use_anchor`. Now every use of it is explicit and exhaustively matched, catching errors like one in the linked issue. This is not a perfect fix but it's a step in the right direction. r? `@oli-obk`
This commit is contained in:
commit
eecfdfb8a1
@ -2,7 +2,7 @@
|
||||
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_middle::mir::Body;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
) -> BodyWithBorrowckFacts<'tcx> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
||||
|
@ -24,7 +24,7 @@
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::mir::{
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
|
||||
PlaceRef, VarDebugInfoContents,
|
||||
@ -130,11 +130,14 @@ fn mir_borrowck<'tcx>(
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
||||
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
|
||||
|
||||
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
do_mir_borrowck(&infcx, input_body, promoted, false).0
|
||||
});
|
||||
let opt_closure_req = tcx
|
||||
.infer_ctxt()
|
||||
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
|
||||
.enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
do_mir_borrowck(&infcx, input_body, promoted, false).0
|
||||
});
|
||||
debug!("mir_borrowck done");
|
||||
|
||||
tcx.arena.alloc(opt_closure_req)
|
||||
|
@ -3,8 +3,8 @@
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::infer::TyCtxtInferExt as _;
|
||||
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
|
||||
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
|
||||
@ -269,59 +269,65 @@ fn infer_opaque_definition_from_instantiation(
|
||||
// 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);
|
||||
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);
|
||||
// HACK This bubble is required for this tests to pass:
|
||||
// type-alias-impl-trait/issue-67844-nested-opaque.rs
|
||||
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).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);
|
||||
// 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.to_def_id(), id_substs),
|
||||
definition_ty,
|
||||
err,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
infcx
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(instantiated_ty.span, body_id),
|
||||
self.tcx.mk_opaque(def_id.to_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);
|
||||
|
||||
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
||||
// tests to pass
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -239,17 +239,31 @@ pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tc
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DefiningAnchor {
|
||||
/// `DefId` of the item.
|
||||
Bind(LocalDefId),
|
||||
/// When opaque types are not resolved, we `Bubble` up, meaning
|
||||
/// return the opaque/hidden type pair from query, for caller of query to handle it.
|
||||
Bubble,
|
||||
/// Used to catch type mismatch errors when handling opaque types.
|
||||
Error,
|
||||
}
|
||||
|
||||
pub struct InferCtxt<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
/// The `DefId` of the item in whose context we are performing inference or typeck.
|
||||
/// It is used to check whether an opaque type use is a defining use.
|
||||
///
|
||||
/// If it is `None`, we can't resolve opaque types here and need to bubble up
|
||||
/// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
|
||||
/// the obligation. This frequently happens for
|
||||
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
|
||||
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
|
||||
pub defining_use_anchor: Option<LocalDefId>,
|
||||
///
|
||||
/// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
|
||||
/// might come up during inference or typeck.
|
||||
pub defining_use_anchor: DefiningAnchor,
|
||||
|
||||
/// During type-checking/inference of a body, `in_progress_typeck_results`
|
||||
/// contains a reference to the typeck results being built up, which are
|
||||
@ -526,7 +540,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
pub struct InferCtxtBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
||||
defining_use_anchor: Option<LocalDefId>,
|
||||
defining_use_anchor: DefiningAnchor,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
@ -535,7 +549,11 @@ pub trait TyCtxtInferExt<'tcx> {
|
||||
|
||||
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
|
||||
InferCtxtBuilder {
|
||||
tcx: self,
|
||||
defining_use_anchor: DefiningAnchor::Error,
|
||||
fresh_typeck_results: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,7 +563,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
/// Will also change the scope for opaque type defining use checks to the given owner.
|
||||
pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self {
|
||||
self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner)));
|
||||
self.with_opaque_type_inference(table_owner)
|
||||
self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner))
|
||||
}
|
||||
|
||||
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
|
||||
@ -554,8 +572,8 @@ pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId)
|
||||
/// It is only meant to be called in two places, for typeck
|
||||
/// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
|
||||
/// in mir borrowck.
|
||||
pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self {
|
||||
self.defining_use_anchor = Some(defining_use_anchor);
|
||||
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
|
||||
self.defining_use_anchor = defining_use_anchor;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
|
||||
use crate::traits;
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use hir::{HirId, OpaqueTyOrigin};
|
||||
@ -101,44 +101,46 @@ pub fn handle_opaque_type(
|
||||
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
||||
ty::Opaque(def_id, substs) if def_id.is_local() => {
|
||||
let def_id = def_id.expect_local();
|
||||
let origin = if self.defining_use_anchor.is_some() {
|
||||
// Check that this is `impl Trait` type is
|
||||
// declared by `parent_def_id` -- i.e., one whose
|
||||
// value we are inferring. At present, this is
|
||||
// always true during the first phase of
|
||||
// type-check, but not always true later on during
|
||||
// NLL. Once we support named opaque types more fully,
|
||||
// this same scenario will be able to arise during all phases.
|
||||
//
|
||||
// Here is an example using type alias `impl Trait`
|
||||
// that indicates the distinction we are checking for:
|
||||
//
|
||||
// ```rust
|
||||
// mod a {
|
||||
// pub type Foo = impl Iterator;
|
||||
// pub fn make_foo() -> Foo { .. }
|
||||
// }
|
||||
//
|
||||
// mod b {
|
||||
// fn foo() -> a::Foo { a::make_foo() }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here, the return type of `foo` references an
|
||||
// `Opaque` indeed, but not one whose value is
|
||||
// presently being inferred. You can get into a
|
||||
// similar situation with closure return types
|
||||
// today:
|
||||
//
|
||||
// ```rust
|
||||
// fn foo() -> impl Iterator { .. }
|
||||
// fn bar() {
|
||||
// let x = || foo(); // returns the Opaque assoc with `foo`
|
||||
// }
|
||||
// ```
|
||||
self.opaque_type_origin(def_id, cause.span)?
|
||||
} else {
|
||||
self.opaque_ty_origin_unchecked(def_id, cause.span)
|
||||
let origin = match self.defining_use_anchor {
|
||||
DefiningAnchor::Bind(_) => {
|
||||
// Check that this is `impl Trait` type is
|
||||
// declared by `parent_def_id` -- i.e., one whose
|
||||
// value we are inferring. At present, this is
|
||||
// always true during the first phase of
|
||||
// type-check, but not always true later on during
|
||||
// NLL. Once we support named opaque types more fully,
|
||||
// this same scenario will be able to arise during all phases.
|
||||
//
|
||||
// Here is an example using type alias `impl Trait`
|
||||
// that indicates the distinction we are checking for:
|
||||
//
|
||||
// ```rust
|
||||
// mod a {
|
||||
// pub type Foo = impl Iterator;
|
||||
// pub fn make_foo() -> Foo { .. }
|
||||
// }
|
||||
//
|
||||
// mod b {
|
||||
// fn foo() -> a::Foo { a::make_foo() }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here, the return type of `foo` references an
|
||||
// `Opaque` indeed, but not one whose value is
|
||||
// presently being inferred. You can get into a
|
||||
// similar situation with closure return types
|
||||
// today:
|
||||
//
|
||||
// ```rust
|
||||
// fn foo() -> impl Iterator { .. }
|
||||
// fn bar() {
|
||||
// let x = || foo(); // returns the Opaque assoc with `foo`
|
||||
// }
|
||||
// ```
|
||||
self.opaque_type_origin(def_id, cause.span)?
|
||||
}
|
||||
DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
|
||||
DefiningAnchor::Error => return None,
|
||||
};
|
||||
if let ty::Opaque(did2, _) = *b.kind() {
|
||||
// We could accept this, but there are various ways to handle this situation, and we don't
|
||||
@ -407,7 +409,10 @@ pub fn register_member_constraints(
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> {
|
||||
let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let parent_def_id = self.defining_use_anchor?;
|
||||
let parent_def_id = match self.defining_use_anchor {
|
||||
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
|
||||
DefiningAnchor::Bind(bind) => bind,
|
||||
};
|
||||
let item_kind = &self.tcx.hir().expect_item(def_id).kind;
|
||||
|
||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
|
||||
|
@ -3,7 +3,7 @@
|
||||
// seems likely that they should eventually be merged into more
|
||||
// general routines.
|
||||
|
||||
use crate::infer::TyCtxtInferExt;
|
||||
use crate::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use crate::traits::{
|
||||
FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
|
||||
Unimplemented,
|
||||
@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(|infcx| {
|
||||
//~^ HACK `Bubble` is required for
|
||||
// this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
|
||||
let obligation_cause = ObligationCause::dummy();
|
||||
@ -69,7 +71,8 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
||||
|
||||
// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
|
||||
// as they will get constrained elsewhere, too.
|
||||
let _opaque_types = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
// (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
|
||||
debug!("Cache miss: {trait_ref:?} => {impl_source:?}");
|
||||
Ok(&*tcx.arena.alloc(impl_source))
|
||||
|
@ -14,7 +14,7 @@
|
||||
use rustc_hir::{ItemKind, Node, PathSegment};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
@ -731,52 +731,52 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
};
|
||||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| {
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter(
|
||||
move |infcx| {
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
|
||||
|
||||
let misc_cause = traits::ObligationCause::misc(span, hir_id);
|
||||
let misc_cause = traits::ObligationCause::misc(span, hir_id);
|
||||
|
||||
match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
|
||||
Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
|
||||
Err(ty_err) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
|
||||
);
|
||||
match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
|
||||
Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
|
||||
Err(ty_err) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Additionally 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(hidden_type.into())).to_predicate(tcx);
|
||||
ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
|
||||
// Additionally 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(hidden_type.into()))
|
||||
.to_predicate(tcx);
|
||||
ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
}
|
||||
|
||||
match origin {
|
||||
// Checked when type checking the function containing them.
|
||||
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
|
||||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
defining_use_anchor,
|
||||
&outlives_environment,
|
||||
);
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up after ourselves
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
});
|
||||
match origin {
|
||||
// Checked when type checking the function containing them.
|
||||
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
|
||||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
defining_use_anchor,
|
||||
&outlives_environment,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Clean up after ourselves
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
||||
|
@ -1460,6 +1460,7 @@ pub fn check_type_bounds<'tcx>(
|
||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
||||
.map(|(bound, span)| {
|
||||
debug!(?bound);
|
||||
// this is where opaque type is found
|
||||
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
||||
|
||||
@ -1481,7 +1482,6 @@ pub fn check_type_bounds<'tcx>(
|
||||
ocx.register_obligations(obligations);
|
||||
ocx.register_obligation(obligation);
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
impl Foo for Concrete {
|
||||
type Item = Concrete;
|
||||
//~^ mismatched types
|
||||
//~^ type mismatch resolving
|
||||
}
|
||||
|
||||
impl Bar for Concrete {
|
||||
|
@ -1,15 +1,25 @@
|
||||
error[E0308]: mismatched types
|
||||
error[E0271]: type mismatch resolving `<Concrete as Bar>::Other == Concrete`
|
||||
--> $DIR/issue-99348-impl-compatibility.rs:8:17
|
||||
|
|
||||
LL | type Tait = impl Sized;
|
||||
| ---------- the expected opaque type
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | type Item = Concrete;
|
||||
| ^^^^^^^^ types differ
|
||||
| ^^^^^^^^ type mismatch resolving `<Concrete as Bar>::Other == Concrete`
|
||||
|
|
||||
= note: expected opaque type `Tait`
|
||||
found struct `Concrete`
|
||||
note: expected this to be `Concrete`
|
||||
--> $DIR/issue-99348-impl-compatibility.rs:13:18
|
||||
|
|
||||
LL | type Other = Tait;
|
||||
| ^^^^
|
||||
= note: expected struct `Concrete`
|
||||
found opaque type `Tait`
|
||||
note: required by a bound in `Foo::Item`
|
||||
--> $DIR/issue-99348-impl-compatibility.rs:17:20
|
||||
|
|
||||
LL | type Item: Bar<Other = Self>;
|
||||
| ^^^^^^^^^^^^ required by this bound in `Foo::Item`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
@ -27,7 +27,7 @@ trait X {
|
||||
struct Y;
|
||||
impl X for Y {
|
||||
async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
|
||||
//~^ ERROR impl has stricter requirements than trait
|
||||
//~^ ERROR has an incompatible type for trait
|
||||
unsafe fn ft2() {} // OK.
|
||||
const fn ft3() {} //~ ERROR functions in traits cannot be declared const
|
||||
extern "C" fn ft4() {}
|
||||
@ -36,7 +36,7 @@ extern "C" fn ft4() {}
|
||||
//~| ERROR functions in traits cannot be declared const
|
||||
//~| ERROR functions cannot be both `const` and `async`
|
||||
//~| ERROR cycle detected
|
||||
//~| ERROR impl has stricter requirements than trait
|
||||
//~| ERROR has an incompatible type for trait
|
||||
}
|
||||
|
||||
impl Y {
|
||||
|
@ -216,23 +216,41 @@ LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:29:9
|
||||
error[E0053]: method `ft1` has an incompatible type for trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:29:24
|
||||
|
|
||||
LL | async fn ft1() {}
|
||||
| ^
|
||||
| |
|
||||
| checked the `Output` of this `async fn`, found opaque type
|
||||
| expected `()`, found opaque type
|
||||
|
|
||||
= note: while checking the return type of the `async fn`
|
||||
note: type in trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:17:23
|
||||
|
|
||||
LL | async fn ft1();
|
||||
| --------------- definition of `ft1` from trait
|
||||
...
|
||||
LL | async fn ft1() {}
|
||||
| ^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
|
||||
| ^
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn() -> impl Future<Output = ()>`
|
||||
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:34:9
|
||||
error[E0053]: method `ft5` has an incompatible type for trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:34:48
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5() {}
|
||||
| ^
|
||||
| |
|
||||
| checked the `Output` of this `async fn`, found opaque type
|
||||
| expected `()`, found opaque type
|
||||
|
|
||||
= note: while checking the return type of the `async fn`
|
||||
note: type in trait
|
||||
--> $DIR/fn-header-semantic-fail.rs:21:47
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5();
|
||||
| --------------------------------------- definition of `ft5` from trait
|
||||
...
|
||||
LL | const async unsafe extern "C" fn ft5() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
|
||||
| ^
|
||||
= note: expected fn pointer `unsafe extern "C" fn()`
|
||||
found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>`
|
||||
|
||||
error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`
|
||||
--> $DIR/fn-header-semantic-fail.rs:34:48
|
||||
@ -308,5 +326,5 @@ LL | | }
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0276, E0379, E0391, E0706.
|
||||
For more information about an error, try `rustc --explain E0276`.
|
||||
Some errors have detailed explanations: E0053, E0379, E0391, E0706.
|
||||
For more information about an error, try `rustc --explain E0053`.
|
||||
|
@ -14,7 +14,7 @@ trait B {
|
||||
impl B for A {
|
||||
async fn associated(); //~ ERROR without body
|
||||
//~^ ERROR cannot be declared `async`
|
||||
//~| ERROR impl has stricter requirements than trait
|
||||
//~| ERROR has an incompatible type for trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -44,16 +44,25 @@ LL | async fn associated();
|
||||
= note: `async` trait functions are not currently supported
|
||||
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
|
||||
error[E0053]: method `associated` has an incompatible type for trait
|
||||
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
|
||||
|
|
||||
LL | async fn associated();
|
||||
| ---------------------- definition of `associated` from trait
|
||||
...
|
||||
| ^
|
||||
| |
|
||||
| checked the `Output` of this `async fn`, found opaque type
|
||||
| expected `()`, found opaque type
|
||||
|
|
||||
= note: while checking the return type of the `async fn`
|
||||
note: type in trait
|
||||
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26
|
||||
|
|
||||
LL | async fn associated();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
|
||||
| ^
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn pointer `fn() -> impl Future<Output = ()>`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0276, E0706.
|
||||
For more information about an error, try `rustc --explain E0276`.
|
||||
Some errors have detailed explanations: E0053, E0706.
|
||||
For more information about an error, try `rustc --explain E0053`.
|
||||
|
@ -3,7 +3,7 @@
|
||||
type Foo = impl Fn() -> Foo;
|
||||
|
||||
fn foo() -> Foo {
|
||||
//~^ ERROR: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
|
||||
//~^ ERROR: overflow evaluating the requirement
|
||||
foo
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
error[E0275]: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
|
||||
error[E0275]: overflow evaluating the requirement `<fn() -> Foo {foo} as FnOnce<()>>::Output == fn() -> Foo {foo}`
|
||||
--> $DIR/issue-53398-cyclic-types.rs:5:13
|
||||
|
|
||||
LL | fn foo() -> Foo {
|
||||
| ^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
18
src/test/ui/type-alias-impl-trait/issue-57961.rs
Normal file
18
src/test/ui/type-alias-impl-trait/issue-57961.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type X = impl Sized;
|
||||
|
||||
trait Foo {
|
||||
type Bar: Iterator<Item = X>;
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
type Bar = std::vec::IntoIter<u32>;
|
||||
//~^ ERROR type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X
|
||||
}
|
||||
|
||||
fn incoherent() {
|
||||
let f: X = 22_i32;
|
||||
}
|
||||
|
||||
fn main() {}
|
20
src/test/ui/type-alias-impl-trait/issue-57961.stderr
Normal file
20
src/test/ui/type-alias-impl-trait/issue-57961.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X`
|
||||
--> $DIR/issue-57961.rs:10:16
|
||||
|
|
||||
LL | type X = impl Sized;
|
||||
| ---------- the expected opaque type
|
||||
...
|
||||
LL | type Bar = std::vec::IntoIter<u32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `u32`
|
||||
|
|
||||
= note: expected opaque type `X`
|
||||
found type `u32`
|
||||
note: required by a bound in `Foo::Bar`
|
||||
--> $DIR/issue-57961.rs:6:24
|
||||
|
|
||||
LL | type Bar: Iterator<Item = X>;
|
||||
| ^^^^^^^^ required by this bound in `Foo::Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
Loading…
Reference in New Issue
Block a user