More tests and tweak comments
This commit is contained in:
parent
af24d0b660
commit
1de894f0c1
@ -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);
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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(&());
|
||||
}
|
@ -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
|
||||
|
@ -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::<()>();
|
||||
}
|
@ -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
|
||||
|
@ -5,7 +5,10 @@ trait Trait {
|
||||
fn method() {}
|
||||
}
|
||||
|
||||
fn test<T: Trait<method(..): Send>>() {}
|
||||
//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
|
||||
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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user