Skip to content

Commit 104aacb

Browse files
Add tests and error messages
1 parent 0308d4a commit 104aacb

File tree

17 files changed

+339
-14
lines changed

17 files changed

+339
-14
lines changed

compiler/rustc_ast_lowering/messages.ftl

+8
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,11 @@ ast_lowering_trait_fn_async =
139139
.label = `async` because of this
140140
.note = `async` trait functions are not currently supported
141141
.note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
142+
143+
ast_lowering_bad_return_type_notation_inputs =
144+
argument types not allowed with return type notation
145+
.suggestion = remove the input types
146+
147+
ast_lowering_bad_return_type_notation_output =
148+
return type not allowed with return type notation
149+
.suggestion = remove the return type

compiler/rustc_ast_lowering/src/errors.rs

+16
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,19 @@ pub struct TraitFnAsync {
347347
#[label]
348348
pub span: Span,
349349
}
350+
351+
#[derive(Diagnostic)]
352+
pub enum BadReturnTypeNotation {
353+
#[diag(ast_lowering_bad_return_type_notation_inputs)]
354+
Inputs {
355+
#[primary_span]
356+
#[suggestion(code = "()", applicability = "maybe-incorrect")]
357+
span: Span,
358+
},
359+
#[diag(ast_lowering_bad_return_type_notation_output)]
360+
Output {
361+
#[primary_span]
362+
#[suggestion(code = "", applicability = "maybe-incorrect")]
363+
span: Span,
364+
},
365+
}

compiler/rustc_ast_lowering/src/lib.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -987,10 +987,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
987987
GenericArgs::AngleBracketed(data) => {
988988
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
989989
}
990-
GenericArgs::Parenthesized(data)
991-
if self.tcx.features().return_type_notation =>
992-
{
993-
// TODO: Check the parens + no return type
990+
GenericArgs::Parenthesized(data) if self.tcx.features().return_type_notation => {
991+
if !data.inputs.is_empty() {
992+
self.tcx.sess.emit_err(errors::BadReturnTypeNotation::Inputs {
993+
span: data.inputs_span,
994+
});
995+
} else if let FnRetTy::Ty(ty) = &data.output {
996+
self.tcx.sess.emit_err(errors::BadReturnTypeNotation::Output {
997+
span: data.inputs_span.shrink_to_hi().to(ty.span),
998+
});
999+
}
9941000
GenericArgsCtor {
9951001
args: Default::default(),
9961002
bindings: &[],
@@ -1000,7 +1006,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10001006
}
10011007
GenericArgs::Parenthesized(data) => {
10021008
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
1003-
// TODO: Add a RTN feature error if the parens are shaped correctly
1009+
// FIXME(return_type_notation): we could issue a feature error
1010+
// if the parens are empty and there's no return type.
10041011
self.lower_angle_bracketed_parameter_data(
10051012
&data.as_angle_bracketed_args(),
10061013
ParamMode::Explicit,

compiler/rustc_hir_analysis/messages.ftl

+11
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,14 @@ hir_analysis_invalid_union_field =
178178
179179
hir_analysis_invalid_union_field_sugg =
180180
wrap the field type in `ManuallyDrop<...>`
181+
182+
hir_analysis_return_type_notation_on_non_rpitit =
183+
return type notation used on function that is not `async` and does not return `impl Trait`
184+
.note = function returns `{$ty}`, which is not compatible with associated type return bounds
185+
.label = this function must be `async` or return `impl Trait`
186+
187+
hir_analysis_return_type_notation_equality_bound =
188+
return type notation is not allowed to use type equality
189+
190+
hir_analysis_return_type_notation_missing_method =
191+
cannot find associated function `{$assoc_name}` in trait `{$trait_name}`

compiler/rustc_hir_analysis/src/astconv/mod.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -1086,9 +1086,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10861086

10871087
let tcx = self.tcx();
10881088

1089-
// TODO: rtn comment goes here
1090-
let associated_return_type_bound =
1091-
binding.gen_args.parenthesized && tcx.features().associated_return_type_bounds;
1089+
let return_type_notation =
1090+
binding.gen_args.parenthesized && tcx.features().return_type_notation;
10921091

10931092
let candidate = if return_type_notation {
10941093
if self.trait_defines_associated_item_named(
@@ -1098,8 +1097,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10981097
) {
10991098
trait_ref
11001099
} else {
1101-
// TODO: error
1102-
todo!()
1100+
return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
1101+
span: binding.span,
1102+
trait_name: tcx.item_name(trait_ref.def_id()),
1103+
assoc_name: binding.item_name.name,
1104+
}));
11031105
}
11041106
} else if self.trait_defines_associated_item_named(
11051107
trait_ref.def_id(),
@@ -1218,7 +1220,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12181220
{
12191221
alias_ty
12201222
} else {
1221-
todo!("found return type of {output:?}");
1223+
return Err(self.tcx().sess.emit_err(
1224+
crate::errors::ReturnTypeNotationOnNonRpitit {
1225+
span: binding.span,
1226+
ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
1227+
fn_span: tcx.hir().span_if_local(assoc_item.def_id),
1228+
note: (),
1229+
},
1230+
));
12221231
};
12231232

12241233
// Finally, move the fn return type's bound vars over to account for the early bound
@@ -1292,9 +1301,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12921301
}
12931302

12941303
match binding.kind {
1295-
ConvertedBindingKind::Equality(..) if associated_return_type_bound => {
1296-
// TODO: error
1297-
todo!()
1304+
ConvertedBindingKind::Equality(..) if return_type_notation => {
1305+
return Err(self.tcx().sess.emit_err(
1306+
crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },
1307+
));
12981308
}
12991309
ConvertedBindingKind::Equality(mut term) => {
13001310
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to

compiler/rustc_hir_analysis/src/errors.rs

+28
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,18 @@ pub(crate) struct InvalidUnionField {
471471
pub note: (),
472472
}
473473

474+
#[derive(Diagnostic)]
475+
#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
476+
pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
477+
#[primary_span]
478+
pub span: Span,
479+
pub ty: Ty<'tcx>,
480+
#[label]
481+
pub fn_span: Option<Span>,
482+
#[note]
483+
pub note: (),
484+
}
485+
474486
#[derive(Subdiagnostic)]
475487
#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")]
476488
pub(crate) struct InvalidUnionFieldSuggestion {
@@ -479,3 +491,19 @@ pub(crate) struct InvalidUnionFieldSuggestion {
479491
#[suggestion_part(code = ">")]
480492
pub hi: Span,
481493
}
494+
495+
#[derive(Diagnostic)]
496+
#[diag(hir_analysis_return_type_notation_equality_bound)]
497+
pub(crate) struct ReturnTypeNotationEqualityBound {
498+
#[primary_span]
499+
pub span: Span,
500+
}
501+
502+
#[derive(Diagnostic)]
503+
#[diag(hir_analysis_return_type_notation_missing_method)]
504+
pub(crate) struct ReturnTypeNotationMissingMethod {
505+
#[primary_span]
506+
pub span: Span,
507+
pub trait_name: Symbol,
508+
pub assoc_name: Symbol,
509+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// edition: 2021
2+
3+
#![feature(return_type_notation, async_fn_in_trait)]
4+
//~^ WARN the feature `return_type_notation` is incomplete
5+
//~| WARN the feature `async_fn_in_trait` is incomplete
6+
7+
trait Trait {
8+
async fn method() {}
9+
}
10+
11+
fn foo<T: Trait<method(i32): Send>>() {}
12+
//~^ ERROR argument types not allowed with return type notation
13+
14+
fn bar<T: Trait<method() -> (): Send>>() {}
15+
//~^ ERROR return type not allowed with return type notation
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/bad-inputs-and-output.rs:3:12
3+
|
4+
LL | #![feature(return_type_notation, async_fn_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/bad-inputs-and-output.rs:3:34
12+
|
13+
LL | #![feature(return_type_notation, async_fn_in_trait)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
17+
18+
error: argument types not allowed with return type notation
19+
--> $DIR/bad-inputs-and-output.rs:11:23
20+
|
21+
LL | fn foo<T: Trait<method(i32): Send>>() {}
22+
| ^^^^^ help: remove the input types: `()`
23+
24+
error: return type not allowed with return type notation
25+
--> $DIR/bad-inputs-and-output.rs:14:25
26+
|
27+
LL | fn bar<T: Trait<method() -> (): Send>>() {}
28+
| ^^^^^^ help: remove the return type
29+
30+
error: aborting due to 2 previous errors; 2 warnings emitted
31+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// revisions: with without
2+
// edition: 2021
3+
//[with] check-pass
4+
5+
#![feature(return_type_notation, async_fn_in_trait)]
6+
//~^ WARN the feature `return_type_notation` is incomplete
7+
//~| WARN the feature `async_fn_in_trait` is incomplete
8+
9+
trait Foo {
10+
async fn method() -> Result<(), ()>;
11+
}
12+
13+
async fn foo<T: Foo>() -> Result<(), ()> {
14+
T::method().await?;
15+
Ok(())
16+
}
17+
18+
fn is_send(_: impl Send) {}
19+
20+
fn test<
21+
#[cfg(with)] T: Foo<method(): Send>,
22+
#[cfg(without)] T: Foo,
23+
>() {
24+
is_send(foo::<T>());
25+
//[without]~^ ERROR future cannot be sent between threads safely
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/basic.rs:5:12
3+
|
4+
LL | #![feature(return_type_notation, async_fn_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/basic.rs:5:34
12+
|
13+
LL | #![feature(return_type_notation, async_fn_in_trait)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
17+
18+
warning: 2 warnings emitted
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/basic.rs:5:12
3+
|
4+
LL | #![feature(return_type_notation, async_fn_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/basic.rs:5:34
12+
|
13+
LL | #![feature(return_type_notation, async_fn_in_trait)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
17+
18+
error: future cannot be sent between threads safely
19+
--> $DIR/basic.rs:24:13
20+
|
21+
LL | is_send(foo::<T>());
22+
| ^^^^^^^^^^ future returned by `foo` is not `Send`
23+
|
24+
= help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
25+
note: future is not `Send` as it awaits another future which is not `Send`
26+
--> $DIR/basic.rs:14:5
27+
|
28+
LL | T::method().await?;
29+
| ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send`
30+
note: required by a bound in `is_send`
31+
--> $DIR/basic.rs:18:20
32+
|
33+
LL | fn is_send(_: impl Send) {}
34+
| ^^^^ required by this bound in `is_send`
35+
36+
error: aborting due to previous error; 2 warnings emitted
37+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition: 2021
2+
3+
#![feature(return_type_notation, async_fn_in_trait)]
4+
//~^ WARN the feature `return_type_notation` is incomplete
5+
//~| WARN the feature `async_fn_in_trait` is incomplete
6+
7+
use std::future::Future;
8+
9+
trait Trait {
10+
async fn method() {}
11+
}
12+
13+
fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
14+
//~^ ERROR return type notation is not allowed to use type equality
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/equality.rs:3:12
3+
|
4+
LL | #![feature(return_type_notation, async_fn_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/equality.rs:3:34
12+
|
13+
LL | #![feature(return_type_notation, async_fn_in_trait)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
17+
18+
error: return type notation is not allowed to use type equality
19+
--> $DIR/equality.rs:13:18
20+
|
21+
LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
24+
error: aborting due to previous error; 2 warnings emitted
25+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// edition: 2021
2+
3+
#![feature(return_type_notation, async_fn_in_trait)]
4+
//~^ WARN the feature `return_type_notation` is incomplete
5+
//~| WARN the feature `async_fn_in_trait` is incomplete
6+
7+
trait Trait {
8+
async fn method() {}
9+
}
10+
11+
fn bar<T: Trait<methid(): Send>>() {}
12+
//~^ ERROR cannot find associated function `methid` in trait `Trait`
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/missing.rs:3:12
3+
|
4+
LL | #![feature(return_type_notation, async_fn_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/missing.rs:3:34
12+
|
13+
LL | #![feature(return_type_notation, async_fn_in_trait)]
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
17+
18+
error: cannot find associated function `methid` in trait `Trait`
19+
--> $DIR/missing.rs:11:17
20+
|
21+
LL | fn bar<T: Trait<methid(): Send>>() {}
22+
| ^^^^^^^^^^^^^^
23+
24+
error: aborting due to previous error; 2 warnings emitted
25+

0 commit comments

Comments
 (0)