1
Fork 0

take opaq types

This commit is contained in:
ouz-a 2022-07-02 16:37:49 +03:00
parent 03d488b48a
commit 7c0fb38095
18 changed files with 293 additions and 185 deletions

View file

@ -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()

View file

@ -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

View file

@ -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
} }

View file

@ -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
} }

View file

@ -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 {

View file

@ -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))

View file

@ -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) {

View file

@ -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();

View file

@ -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 {

View file

@ -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`.

View file

@ -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 {

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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
} }

View file

@ -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

View 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() {}

View 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`.