mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #102161 - compiler-errors:issue-102138, r=tmandry
Resolve async fn signature even without body (e.g., in trait) Fixes #102138 This "bail if no body" behavior was introduced in #69539 to fix #69401, but that ICE does not reproduce any more. The error message changes a bit, but that's all, and I don't think it's a particularly diagnostic bad regression.
This commit is contained in:
commit
11b4510202
@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
sig.decl.has_self(),
|
||||
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
|
||||
&sig.decl.output,
|
||||
)
|
||||
);
|
||||
|
||||
this.record_lifetime_params_for_async(
|
||||
fn_id,
|
||||
sig.header.asyncness.opt_return_id(),
|
||||
);
|
||||
},
|
||||
);
|
||||
return;
|
||||
@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
},
|
||||
);
|
||||
|
||||
// Construct the list of in-scope lifetime parameters for async lowering.
|
||||
// We include all lifetime parameters, either named or "Fresh".
|
||||
// The order of those parameters does not matter, as long as it is
|
||||
// deterministic.
|
||||
if let Some((async_node_id, _)) = async_node_id {
|
||||
let mut extra_lifetime_params = this
|
||||
.r
|
||||
.extra_lifetime_params_map
|
||||
.get(&fn_id)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
for rib in this.lifetime_ribs.iter().rev() {
|
||||
extra_lifetime_params.extend(
|
||||
rib.bindings
|
||||
.iter()
|
||||
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
|
||||
);
|
||||
match rib.kind {
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder, ..
|
||||
} => {
|
||||
if let Some(earlier_fresh) =
|
||||
this.r.extra_lifetime_params_map.get(&binder)
|
||||
{
|
||||
extra_lifetime_params.extend(earlier_fresh);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
this.r
|
||||
.extra_lifetime_params_map
|
||||
.insert(async_node_id, extra_lifetime_params);
|
||||
}
|
||||
this.record_lifetime_params_for_async(fn_id, async_node_id);
|
||||
|
||||
if let Some(body) = body {
|
||||
// Ignore errors in function bodies if this is rustdoc
|
||||
@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
Some((ident.name, ns)),
|
||||
)
|
||||
}
|
||||
|
||||
/// Construct the list of in-scope lifetime parameters for async lowering.
|
||||
/// We include all lifetime parameters, either named or "Fresh".
|
||||
/// The order of those parameters does not matter, as long as it is
|
||||
/// deterministic.
|
||||
fn record_lifetime_params_for_async(
|
||||
&mut self,
|
||||
fn_id: NodeId,
|
||||
async_node_id: Option<(NodeId, Span)>,
|
||||
) {
|
||||
if let Some((async_node_id, _)) = async_node_id {
|
||||
let mut extra_lifetime_params =
|
||||
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
extra_lifetime_params.extend(
|
||||
rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
|
||||
);
|
||||
match rib.kind {
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
||||
if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
|
||||
extra_lifetime_params.extend(earlier_fresh);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LifetimeCountVisitor<'a, 'b> {
|
||||
|
46
src/test/ui/async-await/in-trait/issue-102138.rs
Normal file
46
src/test/ui/async-await/in-trait/issue-102138.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// check-pass
|
||||
// edition:2021
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
async fn yield_now() {}
|
||||
|
||||
trait AsyncIterator {
|
||||
type Item;
|
||||
async fn next(&mut self) -> Option<Self::Item>;
|
||||
}
|
||||
|
||||
struct YieldingRange {
|
||||
counter: u32,
|
||||
stop: u32,
|
||||
}
|
||||
|
||||
impl AsyncIterator for YieldingRange {
|
||||
type Item = u32;
|
||||
|
||||
async fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.counter == self.stop {
|
||||
None
|
||||
} else {
|
||||
let c = self.counter;
|
||||
self.counter += 1;
|
||||
yield_now().await;
|
||||
Some(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_main() {
|
||||
let mut x = YieldingRange { counter: 0, stop: 10 };
|
||||
|
||||
while let Some(v) = x.next().await {
|
||||
println!("Hi: {v}");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = async_main();
|
||||
}
|
11
src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
Normal file
11
src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// check-pass
|
||||
// This is currently stable behavior, which was almost accidentally made an
|
||||
// error in #102161 since there is no test exercising it. I am not sure if
|
||||
// this _should_ be the desired behavior, but at least we should know if it
|
||||
// changes.
|
||||
|
||||
fn main() {}
|
||||
|
||||
trait Foo {
|
||||
fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32);
|
||||
}
|
Loading…
Reference in New Issue
Block a user