More tests and tweak comments

This commit is contained in:
Michael Goulet 2024-09-20 22:59:03 -04:00
parent af24d0b660
commit 1de894f0c1
11 changed files with 298 additions and 11 deletions

View File

@ -1640,9 +1640,9 @@ fn visit_segment_args(
// }
// ```
// and a bound that looks like:
// `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
// `for<'a> T::Trait<'a, x(..): for<'b> Other<'b>>`
// this is going to expand to something like:
// `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
// `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
{
let bound_vars = if let Some(type_def_id) = type_def_id
@ -1853,13 +1853,13 @@ fn uninsert_lifetime_on_error(
// For example, given
// ```
// trait Foo {
// async fn x<'r, T>();
// async fn x<'r>();
// }
// ```
// and a bound that looks like:
// `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
// this is going to expand to something like:
// `for<'a, 'b, 'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
// `for<'a, 'b, 'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
//
// We handle this similarly for associated-type-bound style return-type-notation
// in `visit_segment_args`.
@ -2000,6 +2000,17 @@ fn try_append_return_type_notation_params(
// the new bound vars. We do this because we need to know how many bound vars
// are present on the binder explicitly (i.e. not return-type-notation vars)
// to do bound var shifting correctly in HIR lowering.
//
// For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
// the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
// parent) will include `'a` AND all the early- and late-bound vars of the
// method. But when lowering the RTN type, we just want the list of vars
// we used to resolve the trait ref. We explicitly stored those back onto
// the item segment, since there's no other good place to put them.
//
// See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
// And this is exercised in:
// `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap();
let existing_bound_vars_saved = existing_bound_vars.clone();
existing_bound_vars.extend(bound_vars);

View File

@ -16,4 +16,22 @@ fn bar<T: Trait<method() -> (): Send>>() {}
fn baz<T: Trait<method(): Send>>() {}
//~^ ERROR return type notation arguments must be elided with `..`
fn foo_path<T: Trait>() where T::method(i32): Send {}
//~^ ERROR argument types not allowed with return type notation
fn bar_path<T: Trait>() where T::method() -> (): Send {}
//~^ ERROR return type not allowed with return type notation
fn baz_path<T: Trait>() where T::method(): Send {}
//~^ ERROR return type notation arguments must be elided with `..`
fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
//~^ ERROR expected associated type
fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
//~^ ERROR expected associated type
fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
//~^ ERROR expected associated type
fn main() {}

View File

@ -1,3 +1,21 @@
error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:28:36
|
LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:31:36
|
LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:34:36
|
LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^ not a associated type
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bad-inputs-and-output.rs:3:12
|
@ -25,5 +43,24 @@ error: return type notation arguments must be elided with `..`
LL | fn baz<T: Trait<method(): Send>>() {}
| ^^ help: add `..`: `(..)`
error: aborting due to 3 previous errors; 1 warning emitted
error: argument types not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:19:40
|
LL | fn foo_path<T: Trait>() where T::method(i32): Send {}
| ^^^^^ help: remove the input types: `()`
error: return type not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:22:42
|
LL | fn bar_path<T: Trait>() where T::method() -> (): Send {}
| ^^^^^^ help: remove the return type
error: return type notation arguments must be elided with `..`
--> $DIR/bad-inputs-and-output.rs:25:40
|
LL | fn baz_path<T: Trait>() where T::method(): Send {}
| ^^ help: add `..`: `(..)`
error: aborting due to 9 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0575`.

View File

@ -0,0 +1,52 @@
//@ check-pass
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Trait<'a> {
fn late<'b>(&'b self, _: &'a ()) -> impl Sized;
fn early<'b: 'b>(&'b self, _: &'a ()) -> impl Sized;
}
#[allow(refining_impl_trait_internal)]
impl<'a> Trait<'a> for () {
fn late<'b>(&'b self, _: &'a ()) -> i32 { 1 }
fn early<'b: 'b>(&'b self, _: &'a ()) -> i32 { 1 }
}
trait Other<'c> {}
impl Other<'_> for i32 {}
fn test<T>(t: &T)
where
T: for<'a, 'c> Trait<'a, late(..): Other<'c>>,
// which is basically:
// for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
T: for<'a, 'c> Trait<'a, early(..): Other<'c>>,
// which is basically:
// for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
{
is_other_impl(t.late(&()));
is_other_impl(t.early(&()));
}
fn test_path<T>(t: &T)
where
T: for<'a> Trait<'a>,
for<'a, 'c> <T as Trait<'a>>::late(..): Other<'c>,
// which is basically:
// for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
for<'a, 'c> <T as Trait<'a>>::early(..): Other<'c>,
// which is basically:
// for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
{
is_other_impl(t.late(&()));
is_other_impl(t.early(&()));
}
fn is_other_impl(_: impl for<'c> Other<'c>) {}
fn main() {
test(&());
test(&());
}

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/higher-ranked-bound-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

View File

@ -0,0 +1,42 @@
//@ check-pass
#![allow(non_camel_case_types)]
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
trait Foo {
type test;
fn test() -> impl Bar;
}
fn call_path<T: Foo>()
where
T::test(..): Bar,
{
}
fn call_bound<T: Foo<test(..): Bar>>() {}
trait Bar {}
struct NotBar;
struct YesBar;
impl Bar for YesBar {}
impl Foo for () {
type test = NotBar;
// Use refinement here so we can observe `YesBar: Bar`.
#[allow(refining_impl_trait_internal)]
fn test() -> YesBar {
YesBar
}
}
fn main() {
// If `T::test(..)` resolved to the GAT (erroneously), then this would be
// an error since `<() as Foo>::bar` -- the associated type -- does not
// implement `Bar`, but the return type of the method does.
call_path::<()>();
call_bound::<()>();
}

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/namespace-conflict.rs:4: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

@ -5,7 +5,10 @@ trait Trait {
fn method() {}
}
fn test<T: Trait<method(..): Send>>() {}
fn bound<T: Trait<method(..): Send>>() {}
//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
fn path<T>() where T: Trait, T::method(..): Send {}
//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
fn main() {}

View File

@ -8,15 +8,26 @@ LL | #![feature(return_type_notation)]
= note: `#[warn(incomplete_features)]` on by default
error: return type notation used on function that is not `async` and does not return `impl Trait`
--> $DIR/non-rpitit.rs:8:18
--> $DIR/non-rpitit.rs:8:19
|
LL | fn method() {}
| ----------- this function must be `async` or return `impl Trait`
...
LL | fn test<T: Trait<method(..): Send>>() {}
LL | fn bound<T: Trait<method(..): Send>>() {}
| ^^^^^^^^^^^^^^^^
|
= note: function returns `()`, which is not compatible with associated type return bounds
error: aborting due to 1 previous error; 1 warning emitted
error: return type notation used on function that is not `async` and does not return `impl Trait`
--> $DIR/non-rpitit.rs:11:30
|
LL | fn method() {}
| ----------- this function must be `async` or return `impl Trait`
...
LL | fn path<T>() where T: Trait, T::method(..): Send {}
| ^^^^^^^^^^^^^
|
= note: function returns `()`, which is not compatible with associated type return bounds
error: aborting due to 2 previous errors; 1 warning emitted

View File

@ -0,0 +1,42 @@
#![feature(return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete
fn function() {}
fn not_a_method()
where
function(..): Send,
//~^ ERROR expected function, found function `function`
//~| ERROR return type notation not allowed in this position yet
{
}
fn not_a_method_and_typoed()
where
function(): Send,
//~^ ERROR expected type, found function `function`
{
}
trait Tr {
fn method();
}
// Forgot the `T::`
fn maybe_method_overlaps<T: Tr>()
where
method(..): Send,
//~^ ERROR cannot find function `method` in this scope
//~| ERROR return type notation not allowed in this position yet
{
}
// Forgot the `T::`, AND typoed `(..)` to `()`
fn maybe_method_overlaps_and_typoed<T: Tr>()
where
method(): Send,
//~^ ERROR cannot find type `method` in this scope
{
}
fn main() {}

View File

@ -0,0 +1,49 @@
error[E0575]: expected function, found function `function`
--> $DIR/not-a-method.rs:8:5
|
LL | function(..): Send,
| ^^^^^^^^^^^^ not a function
error[E0573]: expected type, found function `function`
--> $DIR/not-a-method.rs:16:5
|
LL | function(): Send,
| ^^^^^^^^^^ not a type
error[E0576]: cannot find function `method` in this scope
--> $DIR/not-a-method.rs:28:5
|
LL | method(..): Send,
| ^^^^^^ not found in this scope
error[E0412]: cannot find type `method` in this scope
--> $DIR/not-a-method.rs:37:5
|
LL | method(): Send,
| ^^^^^^ not found in this scope
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/not-a-method.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 not allowed in this position yet
--> $DIR/not-a-method.rs:8:5
|
LL | function(..): Send,
| ^^^^^^^^^^^^
error: return type notation not allowed in this position yet
--> $DIR/not-a-method.rs:28:5
|
LL | method(..): Send,
| ^^^^^^^^^^
error: aborting due to 6 previous errors; 1 warning emitted
Some errors have detailed explanations: E0412, E0573, E0575, E0576.
For more information about an error, try `rustc --explain E0412`.