Add missing diagnostics and flesh out tests

This commit is contained in:
Michael Goulet 2024-08-26 16:31:06 -04:00
parent 7c8e281f73
commit 174c3f9519
25 changed files with 508 additions and 19 deletions

View File

@ -494,9 +494,14 @@ enum AllowReturnTypeNotation {
}
enum GenericArgsMode {
/// Allow paren sugar, don't allow RTN.
ParenSugar,
/// Allow RTN, don't allow paren sugar.
ReturnTypeNotation,
// Error if parenthesized generics or RTN are encountered.
Err,
/// Silence errors when lowering generics. Only used with `Res::Err`.
Silence,
}
impl<'a, 'hir> LoweringContext<'a, 'hir> {

View File

@ -111,7 +111,7 @@ pub(crate) fn lower_qpath(
}
}
// Avoid duplicated errors.
Res::Err => GenericArgsMode::ParenSugar,
Res::Err => GenericArgsMode::Silence,
// An error
_ => GenericArgsMode::Err,
};
@ -288,11 +288,12 @@ pub(crate) fn lower_path_segment(
false,
)
}
GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
data,
itctx,
bound_modifier_allowed_features,
),
GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
.lower_parenthesized_parameter_data(
data,
itctx,
bound_modifier_allowed_features,
),
GenericArgsMode::Err => {
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
let sub = if !data.inputs.is_empty() {
@ -330,7 +331,7 @@ pub(crate) fn lower_path_segment(
},
GenericArgs::ParenthesizedElided(span) => {
match generic_args_mode {
GenericArgsMode::ReturnTypeNotation => {
GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
// Ok
}
GenericArgsMode::ParenSugar | GenericArgsMode::Err => {

View File

@ -460,7 +460,7 @@ fn lower_assoc_ty(
[] => (generics.span, format!("<{lt_name}>")),
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
};
mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
fspan: lt_sp,
first: sugg,
sspan: span.with_hi(item_segment.ident.span.lo()),
@ -502,7 +502,7 @@ fn lower_assoc_ty(
}
Ty::new_error(
self.tcx(),
self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
span,
inferred_sugg,
bound,

View File

@ -1886,10 +1886,11 @@ fn try_append_return_type_notation_params(
)
}) =>
{
let Res::Def(DefKind::AssocFn, item_def_id) = path.res else {
bug!();
};
(vec![], item_def_id, item_segment)
match path.res {
Res::Err => return,
Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
_ => bug!("only expected method resolution for fully qualified RTN"),
}
}
// If we have a type-dependent path, then we do need to do some lookup.

View File

@ -780,7 +780,7 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures {
#[derive(Diagnostic)]
#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)]
pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
pub(crate) struct AssociatedItemTraitUninferredGenericParams {
#[primary_span]
pub span: Span,
#[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
@ -796,7 +796,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
applicability = "maybe-incorrect"
)]
pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
#[suggestion_part(code = "{first}")]
pub fspan: Span,
pub first: String,

View File

@ -487,8 +487,16 @@ pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<
let _ =
self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
let Res::Def(DefKind::AssocFn, item_def_id) = path.res else {
bug!("expected RTN to resolve to associated fn");
let item_def_id = match path.res {
Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
Res::Err => {
return Ty::new_error_with_message(
tcx,
hir_ty.span,
"failed to resolve RTN",
);
}
_ => bug!("only expected method resolution for fully qualified RTN"),
};
let trait_def_id = tcx.parent(item_def_id);
@ -605,7 +613,20 @@ fn resolve_type_relative_return_type_notation(
assoc_ident,
span,
)?,
_ => todo!(),
_ => {
if let Err(reported) = qself_ty.error_reported() {
return Err(reported);
} else {
// FIXME(return_type_notation): Provide some structured suggestion here.
let err = struct_span_code_err!(
self.dcx(),
span,
E0223,
"ambiguous associated function"
);
return Err(err.emit());
}
}
};
// Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,

View File

@ -813,7 +813,8 @@ fn lower_path_segment(
}
}
/// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`.
/// Search for a trait bound on a type parameter whose trait defines the associated item
/// given by `assoc_name` and `kind`.
///
/// This fails if there is no such bound in the list of candidates or if there are multiple
/// candidates in which case it reports ambiguity.

View File

@ -0,0 +1,27 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait A {
fn method() -> impl Sized;
}
trait B {
fn method() -> impl Sized;
}
fn ambiguous<T: A + B>()
where
T::method(..): Send,
//~^ ERROR ambiguous associated function `method` in bounds of `T`
{
}
trait Sub: A + B {}
fn ambiguous_via_supertrait<T: Sub>()
where
T::method(..): Send,
//~^ ERROR ambiguous associated function `method` in bounds of `T`
{
}
fn main() {}

View File

@ -0,0 +1,54 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-ambiguous.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0221]: ambiguous associated function `method` in bounds of `T`
--> $DIR/path-ambiguous.rs:13:5
|
LL | fn method() -> impl Sized;
| -------------------------- ambiguous `method` from `A`
...
LL | fn method() -> impl Sized;
| -------------------------- ambiguous `method` from `B`
...
LL | T::method(..): Send,
| ^^^^^^^^^^^^^ ambiguous associated function `method`
|
help: use fully-qualified syntax to disambiguate
|
LL | <T as B>::method(..): Send,
| ~~~~~~~~~~
help: use fully-qualified syntax to disambiguate
|
LL | <T as A>::method(..): Send,
| ~~~~~~~~~~
error[E0221]: ambiguous associated function `method` in bounds of `T`
--> $DIR/path-ambiguous.rs:22:5
|
LL | fn method() -> impl Sized;
| -------------------------- ambiguous `method` from `A`
...
LL | fn method() -> impl Sized;
| -------------------------- ambiguous `method` from `B`
...
LL | T::method(..): Send,
| ^^^^^^^^^^^^^ ambiguous associated function `method`
|
help: use fully-qualified syntax to disambiguate
|
LL | <T as B>::method(..): Send,
| ~~~~~~~~~~
help: use fully-qualified syntax to disambiguate
|
LL | <T as A>::method(..): Send,
| ~~~~~~~~~~
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0221`.

View File

@ -0,0 +1,25 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait A<'a> {
fn method() -> impl Sized;
}
trait B: for<'a> A<'a> {}
fn higher_ranked<T>()
where
T: for<'a> A<'a>,
T::method(..): Send,
//~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
{
}
fn higher_ranked_via_supertrait<T>()
where
T: B,
T::method(..): Send,
//~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
{
}
fn main() {}

View File

@ -0,0 +1,34 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-higher-ranked.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
--> $DIR/path-higher-ranked.rs:12:5
|
LL | T::method(..): Send,
| ^^^^^^^^^^^^^
|
help: use a fully qualified path with inferred lifetimes
|
LL | <T as A<'_>>::method(..): Send,
| ~~~~~~~~~~~~~~
error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
--> $DIR/path-higher-ranked.rs:20:5
|
LL | T::method(..): Send,
| ^^^^^^^^^^^^^
|
help: use a fully qualified path with inferred lifetimes
|
LL | <T as A<'_>>::method(..): Send,
| ~~~~~~~~~~~~~~
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0212`.

View File

@ -0,0 +1,25 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait A {
#[allow(non_camel_case_types)]
type bad;
}
fn fully_qualified<T: A>()
where
<T as A>::method(..): Send,
//~^ ERROR cannot find method or associated constant `method` in trait `A`
<T as A>::bad(..): Send,
//~^ ERROR expected method or associated constant, found associated type `A::bad`
{
}
fn type_dependent<T: A>()
where
T::method(..): Send,
//~^ associated function `method` not found for `T`
{
}
fn main() {}

View File

@ -0,0 +1,33 @@
error[E0576]: cannot find method or associated constant `method` in trait `A`
--> $DIR/path-missing.rs:11:15
|
LL | <T as A>::method(..): Send,
| ^^^^^^ not found in `A`
error[E0575]: expected method or associated constant, found associated type `A::bad`
--> $DIR/path-missing.rs:13:5
|
LL | <T as A>::bad(..): Send,
| ^^^^^^^^^^^^^^^^^
|
= note: can't use a type alias as a constructor
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-missing.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0220]: associated function `method` not found for `T`
--> $DIR/path-missing.rs:20:8
|
LL | T::method(..): Send,
| ^^^^^^ associated function `method` not found
error: aborting due to 3 previous errors; 1 warning emitted
Some errors have detailed explanations: E0220, E0575, E0576.
For more information about an error, try `rustc --explain E0220`.

View File

@ -0,0 +1,15 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Trait {
fn method() -> impl Sized;
}
fn test()
where
Trait::method(..): Send,
//~^ ERROR ambiguous associated type
{
}
fn main() {}

View File

@ -0,0 +1,23 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-no-qself.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0223]: ambiguous associated type
--> $DIR/path-no-qself.rs:10:5
|
LL | Trait::method(..): Send,
| ^^^^^^^^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
|
LL | <Example as Trait>::method: Send,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0223`.

View File

@ -0,0 +1,21 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Trait {
fn method() -> impl Sized;
}
struct Adt;
fn non_param_qself()
where
<()>::method(..): Send,
//~^ ERROR ambiguous associated function
i32::method(..): Send,
//~^ ERROR ambiguous associated function
Adt::method(..): Send,
//~^ ERROR ambiguous associated function
{
}
fn main() {}

View File

@ -0,0 +1,30 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-non-param-qself.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0223]: ambiguous associated function
--> $DIR/path-non-param-qself.rs:12:5
|
LL | <()>::method(..): Send,
| ^^^^^^^^^^^^^^^^
error[E0223]: ambiguous associated function
--> $DIR/path-non-param-qself.rs:14:5
|
LL | i32::method(..): Send,
| ^^^^^^^^^^^^^^^
error[E0223]: ambiguous associated function
--> $DIR/path-non-param-qself.rs:16:5
|
LL | Adt::method(..): Send,
| ^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0223`.

View File

@ -0,0 +1,16 @@
//@ check-pass
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Foo {
fn method() -> impl Sized;
}
trait Bar: Foo {
fn other()
where
Self::method(..): Send;
}
fn main() {}

View File

@ -0,0 +1,11 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-self-qself.rs:3:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -0,0 +1,22 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Foo {
fn method<T>() -> impl Sized;
}
fn test<T: Foo>()
where
<T as Foo>::method(..): Send,
//~^ ERROR return type notation is not allowed for functions that have type parameters
{
}
fn test_type_dependent<T: Foo>()
where
<T as Foo>::method(..): Send,
//~^ ERROR return type notation is not allowed for functions that have type parameters
{
}
fn main() {}

View File

@ -0,0 +1,29 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-type-param.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error: return type notation is not allowed for functions that have type parameters
--> $DIR/path-type-param.rs:10:5
|
LL | fn method<T>() -> impl Sized;
| - type parameter declared here
...
LL | <T as Foo>::method(..): Send,
| ^^^^^^^^^^^^^^^^^^^^^^
error: return type notation is not allowed for functions that have type parameters
--> $DIR/path-type-param.rs:17:5
|
LL | fn method<T>() -> impl Sized;
| - type parameter declared here
...
LL | <T as Foo>::method(..): Send,
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors; 1 warning emitted

View File

@ -0,0 +1,25 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Trait {
fn method() -> impl Sized;
}
struct DoesntWork;
impl Trait for DoesntWork {
fn method() -> impl Sized {
std::ptr::null_mut::<()>()
// This isn't `Send`.
}
}
fn test<T: Trait>()
where
T::method(..): Send,
{
}
fn main() {
test::<DoesntWork>();
//~^ ERROR `*mut ()` cannot be sent between threads safely
}

View File

@ -0,0 +1,36 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-unsatisfied.rs:1:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `*mut ()` cannot be sent between threads safely
--> $DIR/path-unsatisfied.rs:23:12
|
LL | fn method() -> impl Sized {
| ---------- within this `impl Sized`
...
LL | test::<DoesntWork>();
| ^^^^^^^^^^ `*mut ()` cannot be sent between threads safely
|
= help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`, which is required by `impl Sized: Send`
note: required because it appears within the type `impl Sized`
--> $DIR/path-unsatisfied.rs:10:20
|
LL | fn method() -> impl Sized {
| ^^^^^^^^^^
note: required by a bound in `test`
--> $DIR/path-unsatisfied.rs:18:20
|
LL | fn test<T: Trait>()
| ---- required by a bound in this function
LL | where
LL | T::method(..): Send,
| ^^^^ required by this bound in `test`
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,23 @@
//@ check-pass
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Trait {
fn method() -> impl Sized;
}
struct Works;
impl Trait for Works {
fn method() -> impl Sized {}
}
fn test<T: Trait>()
where
T::method(..): Send,
{
}
fn main() {
test::<Works>();
}

View File

@ -0,0 +1,11 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/path-works.rs:3:12
|
LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted