Skip to content

Commit 11b4510

Browse files
authored
Rollup merge of rust-lang#102161 - compiler-errors:issue-102138, r=tmandry
Resolve async fn signature even without body (e.g., in trait) Fixes rust-lang#102138 This "bail if no body" behavior was introduced in rust-lang#69539 to fix rust-lang#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.
2 parents 16de1fd + e87fcc0 commit 11b4510

File tree

3 files changed

+94
-36
lines changed

3 files changed

+94
-36
lines changed

compiler/rustc_resolve/src/late.rs

+37-36
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
805805
sig.decl.has_self(),
806806
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
807807
&sig.decl.output,
808-
)
808+
);
809+
810+
this.record_lifetime_params_for_async(
811+
fn_id,
812+
sig.header.asyncness.opt_return_id(),
813+
);
809814
},
810815
);
811816
return;
@@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
847852
},
848853
);
849854

850-
// Construct the list of in-scope lifetime parameters for async lowering.
851-
// We include all lifetime parameters, either named or "Fresh".
852-
// The order of those parameters does not matter, as long as it is
853-
// deterministic.
854-
if let Some((async_node_id, _)) = async_node_id {
855-
let mut extra_lifetime_params = this
856-
.r
857-
.extra_lifetime_params_map
858-
.get(&fn_id)
859-
.cloned()
860-
.unwrap_or_default();
861-
for rib in this.lifetime_ribs.iter().rev() {
862-
extra_lifetime_params.extend(
863-
rib.bindings
864-
.iter()
865-
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
866-
);
867-
match rib.kind {
868-
LifetimeRibKind::Item => break,
869-
LifetimeRibKind::AnonymousCreateParameter {
870-
binder, ..
871-
} => {
872-
if let Some(earlier_fresh) =
873-
this.r.extra_lifetime_params_map.get(&binder)
874-
{
875-
extra_lifetime_params.extend(earlier_fresh);
876-
}
877-
}
878-
_ => {}
879-
}
880-
}
881-
this.r
882-
.extra_lifetime_params_map
883-
.insert(async_node_id, extra_lifetime_params);
884-
}
855+
this.record_lifetime_params_for_async(fn_id, async_node_id);
885856

886857
if let Some(body) = body {
887858
// Ignore errors in function bodies if this is rustdoc
@@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
39263897
Some((ident.name, ns)),
39273898
)
39283899
}
3900+
3901+
/// Construct the list of in-scope lifetime parameters for async lowering.
3902+
/// We include all lifetime parameters, either named or "Fresh".
3903+
/// The order of those parameters does not matter, as long as it is
3904+
/// deterministic.
3905+
fn record_lifetime_params_for_async(
3906+
&mut self,
3907+
fn_id: NodeId,
3908+
async_node_id: Option<(NodeId, Span)>,
3909+
) {
3910+
if let Some((async_node_id, _)) = async_node_id {
3911+
let mut extra_lifetime_params =
3912+
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
3913+
for rib in self.lifetime_ribs.iter().rev() {
3914+
extra_lifetime_params.extend(
3915+
rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
3916+
);
3917+
match rib.kind {
3918+
LifetimeRibKind::Item => break,
3919+
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
3920+
if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
3921+
extra_lifetime_params.extend(earlier_fresh);
3922+
}
3923+
}
3924+
_ => {}
3925+
}
3926+
}
3927+
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
3928+
}
3929+
}
39293930
}
39303931

39313932
struct LifetimeCountVisitor<'a, 'b> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// check-pass
2+
// edition:2021
3+
4+
#![feature(async_fn_in_trait)]
5+
#![allow(incomplete_features)]
6+
7+
use std::future::Future;
8+
9+
async fn yield_now() {}
10+
11+
trait AsyncIterator {
12+
type Item;
13+
async fn next(&mut self) -> Option<Self::Item>;
14+
}
15+
16+
struct YieldingRange {
17+
counter: u32,
18+
stop: u32,
19+
}
20+
21+
impl AsyncIterator for YieldingRange {
22+
type Item = u32;
23+
24+
async fn next(&mut self) -> Option<Self::Item> {
25+
if self.counter == self.stop {
26+
None
27+
} else {
28+
let c = self.counter;
29+
self.counter += 1;
30+
yield_now().await;
31+
Some(c)
32+
}
33+
}
34+
}
35+
36+
async fn async_main() {
37+
let mut x = YieldingRange { counter: 0, stop: 10 };
38+
39+
while let Some(v) = x.next().await {
40+
println!("Hi: {v}");
41+
}
42+
}
43+
44+
fn main() {
45+
let _ = async_main();
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
// This is currently stable behavior, which was almost accidentally made an
3+
// error in #102161 since there is no test exercising it. I am not sure if
4+
// this _should_ be the desired behavior, but at least we should know if it
5+
// changes.
6+
7+
fn main() {}
8+
9+
trait Foo {
10+
fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32);
11+
}

0 commit comments

Comments
 (0)