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:
Dylan DPC 2022-07-20 16:17:19 +05:30 committed by GitHub
commit eecfdfb8a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 293 additions and 185 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
impl Foo for Concrete {
type Item = Concrete;
//~^ mismatched types
//~^ type mismatch resolving
}
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
|
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`.

View File

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

View File

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

View File

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

View File

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

View File

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

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

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