Skip to content

Commit

Permalink
More tests and tweak comments
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 21, 2024
1 parent af24d0b commit 1de894f
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 11 deletions.
19 changes: 15 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,9 +1640,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// }
// ```
// 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
Expand Down Expand Up @@ -1853,13 +1853,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// 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`.
Expand Down Expand Up @@ -2000,6 +2000,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
@@ -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
|
Expand Down Expand Up @@ -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`.
Original file line number Diff line number Diff line change
@@ -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(&());
}
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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::<()>();
}
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 1de894f

Please sign in to comment.