mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Fix mixing lazy TAIT and RPIT in their defining scopes
This commit is contained in:
parent
4f6e27d4cf
commit
2aa49d4005
@ -95,6 +95,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
|
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
|
||||||
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) => {
|
ty::Opaque(def_id, substs) => {
|
||||||
|
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)
|
||||||
|
};
|
||||||
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
|
||||||
// want to make a decision on it right now. Likely this case is so super rare anyway, that
|
// want to make a decision on it right now. Likely this case is so super rare anyway, that
|
||||||
@ -126,45 +165,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
cause.clone(),
|
cause.clone(),
|
||||||
param_env,
|
param_env,
|
||||||
b,
|
b,
|
||||||
if self.defining_use_anchor.is_some() {
|
origin,
|
||||||
// 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)
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
28
src/test/ui/impl-trait/async_scope_creep.rs
Normal file
28
src/test/ui/impl-trait/async_scope_creep.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
// edition:2021
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
struct Pending {}
|
||||||
|
|
||||||
|
struct CantOpen {}
|
||||||
|
|
||||||
|
trait AsyncRead {}
|
||||||
|
|
||||||
|
impl AsyncRead for i32 {}
|
||||||
|
|
||||||
|
type PendingReader<'a> = impl AsyncRead + 'a;
|
||||||
|
|
||||||
|
type OpeningReadFuture<'a> =
|
||||||
|
impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
|
||||||
|
|
||||||
|
impl Pending {
|
||||||
|
async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
|
||||||
|
Ok(42)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_fut(&mut self) -> OpeningReadFuture<'_> {
|
||||||
|
self.read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user