take opaq types
This commit is contained in:
parent
03d488b48a
commit
7c0fb38095
18 changed files with 293 additions and 185 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||||
use rustc_middle::mir::Body;
|
use rustc_middle::mir::Body;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
|
||||||
def: ty::WithOptConstParam<LocalDefId>,
|
def: ty::WithOptConstParam<LocalDefId>,
|
||||||
) -> BodyWithBorrowckFacts<'tcx> {
|
) -> BodyWithBorrowckFacts<'tcx> {
|
||||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
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 input_body: &Body<'_> = &input_body.borrow();
|
||||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||||
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
||||||
|
|
|
@ -24,7 +24,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_index::bit_set::ChunkedBitSet;
|
use rustc_index::bit_set::ChunkedBitSet;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
|
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
|
||||||
PlaceRef, VarDebugInfoContents,
|
PlaceRef, VarDebugInfoContents,
|
||||||
|
@ -130,7 +130,10 @@ fn mir_borrowck<'tcx>(
|
||||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
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 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 opt_closure_req = tcx
|
||||||
|
.infer_ctxt()
|
||||||
|
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
|
||||||
|
.enter(|infcx| {
|
||||||
let input_body: &Body<'_> = &input_body.borrow();
|
let input_body: &Body<'_> = &input_body.borrow();
|
||||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||||
do_mir_borrowck(&infcx, input_body, promoted, false).0
|
do_mir_borrowck(&infcx, input_body, promoted, false).0
|
||||||
|
|
|
@ -3,8 +3,8 @@ use rustc_data_structures::vec_map::VecMap;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::OpaqueTyOrigin;
|
use rustc_hir::OpaqueTyOrigin;
|
||||||
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
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::TyCtxtInferExt as _;
|
||||||
|
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
|
||||||
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
|
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
|
||||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
|
||||||
|
@ -269,7 +269,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
|
// 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 param_env = self.tcx.param_env(def_id);
|
||||||
let body_id = self.tcx.local_def_id_to_hir_id(def_id);
|
let body_id = self.tcx.local_def_id_to_hir_id(def_id);
|
||||||
self.tcx.infer_ctxt().enter(move |infcx| {
|
// 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.
|
// 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
|
// 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.
|
// hidden type is well formed even without those bounds.
|
||||||
|
@ -296,7 +299,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
infcx
|
infcx
|
||||||
.report_mismatched_types(
|
.report_mismatched_types(
|
||||||
&ObligationCause::misc(instantiated_ty.span, body_id),
|
&ObligationCause::misc(instantiated_ty.span, body_id),
|
||||||
self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
|
self.tcx.mk_opaque(def_id, id_substs),
|
||||||
definition_ty,
|
definition_ty,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
@ -313,6 +316,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
// version.
|
// version.
|
||||||
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
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();
|
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
|
@ -321,7 +326,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
infcx.report_fulfillment_errors(&errors, None, false);
|
infcx.report_fulfillment_errors(&errors, None, false);
|
||||||
self.tcx.ty_error()
|
self.tcx.ty_error()
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
definition_ty
|
definition_ty
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,17 +239,31 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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 struct InferCtxt<'a, 'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
|
|
||||||
/// The `DefId` of the item in whose context we are performing inference or typeck.
|
/// 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.
|
/// 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
|
/// the obligation. This frequently happens for
|
||||||
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
|
/// 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.
|
/// 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`
|
/// During type-checking/inference of a body, `in_progress_typeck_results`
|
||||||
/// contains a reference to the typeck results being built up, which are
|
/// contains a reference to the typeck results being built up, which are
|
||||||
|
@ -526,7 +540,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
|
||||||
pub struct InferCtxtBuilder<'tcx> {
|
pub struct InferCtxtBuilder<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
||||||
defining_use_anchor: Option<LocalDefId>,
|
defining_use_anchor: DefiningAnchor,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TyCtxtInferExt<'tcx> {
|
pub trait TyCtxtInferExt<'tcx> {
|
||||||
|
@ -535,7 +549,11 @@ pub trait TyCtxtInferExt<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||||
fn infer_ctxt(self) -> InferCtxtBuilder<'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.
|
/// 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 {
|
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.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,
|
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
|
||||||
|
@ -554,8 +572,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||||
/// It is only meant to be called in two places, for typeck
|
/// 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
|
/// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
|
||||||
/// in mir borrowck.
|
/// in mir borrowck.
|
||||||
pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self {
|
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
|
||||||
self.defining_use_anchor = Some(defining_use_anchor);
|
self.defining_use_anchor = defining_use_anchor;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::infer::{InferCtxt, InferOk};
|
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
use hir::def_id::{DefId, LocalDefId};
|
use hir::def_id::{DefId, LocalDefId};
|
||||||
use hir::{HirId, OpaqueTyOrigin};
|
use hir::{HirId, OpaqueTyOrigin};
|
||||||
|
@ -101,7 +101,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
||||||
ty::Opaque(def_id, substs) if def_id.is_local() => {
|
ty::Opaque(def_id, substs) if def_id.is_local() => {
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
let origin = if self.defining_use_anchor.is_some() {
|
let origin = match self.defining_use_anchor {
|
||||||
|
DefiningAnchor::Bind(_) => {
|
||||||
// Check that this is `impl Trait` type is
|
// Check that this is `impl Trait` type is
|
||||||
// declared by `parent_def_id` -- i.e., one whose
|
// declared by `parent_def_id` -- i.e., one whose
|
||||||
// value we are inferring. At present, this is
|
// value we are inferring. At present, this is
|
||||||
|
@ -137,8 +138,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
self.opaque_type_origin(def_id, cause.span)?
|
self.opaque_type_origin(def_id, cause.span)?
|
||||||
} else {
|
}
|
||||||
self.opaque_ty_origin_unchecked(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() {
|
if let ty::Opaque(did2, _) = *b.kind() {
|
||||||
// We could accept this, but there are various ways to handle this situation, and we don't
|
// We could accept this, but there are various ways to handle this situation, and we don't
|
||||||
|
@ -407,7 +409,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
#[instrument(skip(self), level = "trace")]
|
#[instrument(skip(self), level = "trace")]
|
||||||
pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> {
|
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 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 item_kind = &self.tcx.hir().expect_item(def_id).kind;
|
||||||
|
|
||||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
|
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// seems likely that they should eventually be merged into more
|
// seems likely that they should eventually be merged into more
|
||||||
// general routines.
|
// general routines.
|
||||||
|
|
||||||
use crate::infer::TyCtxtInferExt;
|
use crate::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
|
FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
|
||||||
Unimplemented,
|
Unimplemented,
|
||||||
|
@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
||||||
|
|
||||||
// Do the initial selection for the obligation. This yields the
|
// Do the initial selection for the obligation. This yields the
|
||||||
// shallow result we are looking for -- that is, what specific impl.
|
// 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 mut selcx = SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let obligation_cause = ObligationCause::dummy();
|
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
|
// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
|
||||||
// as they will get constrained elsewhere, too.
|
// 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:?}");
|
debug!("Cache miss: {trait_ref:?} => {impl_source:?}");
|
||||||
Ok(&*tcx.arena.alloc(impl_source))
|
Ok(&*tcx.arena.alloc(impl_source))
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{ItemKind, Node, PathSegment};
|
use rustc_hir::{ItemKind, Node, PathSegment};
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
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_infer::traits::Obligation;
|
||||||
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
|
@ -731,7 +731,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
};
|
};
|
||||||
let param_env = tcx.param_env(defining_use_anchor);
|
let param_env = tcx.param_env(defining_use_anchor);
|
||||||
|
|
||||||
tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| {
|
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter(
|
||||||
|
move |infcx| {
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
|
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
|
||||||
|
|
||||||
|
@ -750,8 +751,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
// Additionally require the hidden type to be well-formed with only the generics of the opaque type.
|
// 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
|
// 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.
|
// hidden type is well formed even without those bounds.
|
||||||
let predicate =
|
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into()))
|
||||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx);
|
.to_predicate(tcx);
|
||||||
ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
|
ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
|
||||||
|
|
||||||
// Check that all obligations are satisfied by the implementation's
|
// Check that all obligations are satisfied by the implementation's
|
||||||
|
@ -760,7 +761,6 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.report_fulfillment_errors(&errors, None, false);
|
infcx.report_fulfillment_errors(&errors, None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
match origin {
|
match origin {
|
||||||
// Checked when type checking the function containing them.
|
// Checked when type checking the function containing them.
|
||||||
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
|
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
|
||||||
|
@ -773,10 +773,10 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up after ourselves
|
// Clean up after ourselves
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
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(|e| e.map_bound(|e| *e).transpose_tuple2())
|
||||||
.map(|(bound, span)| {
|
.map(|(bound, span)| {
|
||||||
debug!(?bound);
|
debug!(?bound);
|
||||||
|
// this is where opaque type is found
|
||||||
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
||||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
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_obligations(obligations);
|
||||||
ocx.register_obligation(obligation);
|
ocx.register_obligation(obligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all obligations are satisfied by the implementation's
|
// Check that all obligations are satisfied by the implementation's
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
|
|
|
@ -6,7 +6,7 @@ type Tait = impl Sized;
|
||||||
|
|
||||||
impl Foo for Concrete {
|
impl Foo for Concrete {
|
||||||
type Item = Concrete;
|
type Item = Concrete;
|
||||||
//~^ mismatched types
|
//~^ type mismatch resolving
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bar for Concrete {
|
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
|
--> $DIR/issue-99348-impl-compatibility.rs:8:17
|
||||||
|
|
|
|
||||||
LL | type Tait = impl Sized;
|
LL | type Tait = impl Sized;
|
||||||
| ---------- the expected opaque type
|
| ---------- the found opaque type
|
||||||
...
|
...
|
||||||
LL | type Item = Concrete;
|
LL | type Item = Concrete;
|
||||||
| ^^^^^^^^ types differ
|
| ^^^^^^^^ type mismatch resolving `<Concrete as Bar>::Other == Concrete`
|
||||||
|
|
|
|
||||||
= note: expected opaque type `Tait`
|
note: expected this to be `Concrete`
|
||||||
found struct `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
|
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 @@ fn main() {
|
||||||
struct Y;
|
struct Y;
|
||||||
impl X for Y {
|
impl X for Y {
|
||||||
async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
|
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.
|
unsafe fn ft2() {} // OK.
|
||||||
const fn ft3() {} //~ ERROR functions in traits cannot be declared const
|
const fn ft3() {} //~ ERROR functions in traits cannot be declared const
|
||||||
extern "C" fn ft4() {}
|
extern "C" fn ft4() {}
|
||||||
|
@ -36,7 +36,7 @@ fn main() {
|
||||||
//~| ERROR functions in traits cannot be declared const
|
//~| ERROR functions in traits cannot be declared const
|
||||||
//~| ERROR functions cannot be both `const` and `async`
|
//~| ERROR functions cannot be both `const` and `async`
|
||||||
//~| ERROR cycle detected
|
//~| ERROR cycle detected
|
||||||
//~| ERROR impl has stricter requirements than trait
|
//~| ERROR has an incompatible type for trait
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Y {
|
impl Y {
|
||||||
|
|
|
@ -216,23 +216,41 @@ LL | | }
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
error[E0053]: method `ft1` has an incompatible type for trait
|
||||||
--> $DIR/fn-header-semantic-fail.rs:29:9
|
--> $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();
|
LL | async fn ft1();
|
||||||
| --------------- definition of `ft1` from trait
|
| ^
|
||||||
...
|
= note: expected fn pointer `fn()`
|
||||||
LL | async fn ft1() {}
|
found fn pointer `fn() -> impl Future<Output = ()>`
|
||||||
| ^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
|
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
error[E0053]: method `ft5` has an incompatible type for trait
|
||||||
--> $DIR/fn-header-semantic-fail.rs:34:9
|
--> $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();
|
LL | const async unsafe extern "C" fn ft5();
|
||||||
| --------------------------------------- definition of `ft5` from trait
|
| ^
|
||||||
...
|
= note: expected fn pointer `unsafe extern "C" fn()`
|
||||||
LL | const async unsafe extern "C" fn ft5() {}
|
found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>`
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
|
|
||||||
|
|
||||||
error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`
|
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
|
--> $DIR/fn-header-semantic-fail.rs:34:48
|
||||||
|
@ -308,5 +326,5 @@ LL | | }
|
||||||
|
|
||||||
error: aborting due to 23 previous errors
|
error: aborting due to 23 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0276, E0379, E0391, E0706.
|
Some errors have detailed explanations: E0053, E0379, E0391, E0706.
|
||||||
For more information about an error, try `rustc --explain E0276`.
|
For more information about an error, try `rustc --explain E0053`.
|
||||||
|
|
|
@ -14,7 +14,7 @@ trait B {
|
||||||
impl B for A {
|
impl B for A {
|
||||||
async fn associated(); //~ ERROR without body
|
async fn associated(); //~ ERROR without body
|
||||||
//~^ ERROR cannot be declared `async`
|
//~^ ERROR cannot be declared `async`
|
||||||
//~| ERROR impl has stricter requirements than trait
|
//~| ERROR has an incompatible type for trait
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -44,16 +44,25 @@ LL | async fn associated();
|
||||||
= note: `async` trait functions are not currently supported
|
= note: `async` trait functions are not currently supported
|
||||||
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
error[E0053]: method `associated` has an incompatible type for trait
|
||||||
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
|
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
|
||||||
|
|
|
|
||||||
LL | async fn associated();
|
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();
|
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
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0276, E0706.
|
Some errors have detailed explanations: E0053, E0706.
|
||||||
For more information about an error, try `rustc --explain E0276`.
|
For more information about an error, try `rustc --explain E0053`.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
type Foo = impl Fn() -> Foo;
|
type Foo = impl Fn() -> Foo;
|
||||||
|
|
||||||
fn foo() -> Foo {
|
fn foo() -> Foo {
|
||||||
//~^ ERROR: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
|
//~^ ERROR: overflow evaluating the requirement
|
||||||
foo
|
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
|
--> $DIR/issue-53398-cyclic-types.rs:5:13
|
||||||
|
|
|
|
||||||
LL | fn foo() -> Foo {
|
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
|
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…
Add table
Add a link
Reference in a new issue