Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #93933

Merged
merged 19 commits into from
Feb 12, 2022
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b79fc92
fix ICE when parsing lifetime as function argument
compiler-errors Feb 2, 2022
8b13fd4
Add pretty printer test for use trees
dtolnay Feb 8, 2022
d1b9e4a
Pretty print ItemKind::Use in rustfmt style
dtolnay Feb 8, 2022
b64a822
Bless use tree pretty print test
dtolnay Feb 8, 2022
a38ff48
Add some known GAT bugs as tests
jackh726 Feb 8, 2022
3a1ffea
linkchecker: fix panic on directory symlinks
schopin-pro Feb 11, 2022
9322d09
Check that error code explanations are listed in error_codes.rs
GuillaumeGomez Feb 11, 2022
9b17e2d
Add 2 tests
matthiaskrgr Dec 14, 2021
087fb23
Add missing E0192 in the error code listing
GuillaumeGomez Feb 11, 2022
5be9e79
Update expr.rs
compiler-errors Feb 12, 2022
56d43a2
Add missing release notes for #85200
nsunderland1 Feb 12, 2022
ba42215
Fix line number
jackh726 Feb 12, 2022
661be4c
Rollup merge of #91908 - matthiaskrgr:ices, r=jackh726
matthiaskrgr Feb 12, 2022
602898a
Rollup merge of #93595 - compiler-errors:ice-on-lifetime-arg, r=jackh726
matthiaskrgr Feb 12, 2022
36461e0
Rollup merge of #93757 - jackh726:gat-bug-tests, r=nikomatsakis
matthiaskrgr Feb 12, 2022
f30f6de
Rollup merge of #93759 - dtolnay:usetree, r=nagisa
matthiaskrgr Feb 12, 2022
475b45f
Rollup merge of #93897 - schopin-pro:linkchecker-symlink, r=Mark-Simu…
matthiaskrgr Feb 12, 2022
16f490f
Rollup merge of #93898 - GuillaumeGomez:error-code-check, r=Mark-Simu…
matthiaskrgr Feb 12, 2022
0e3ecd2
Rollup merge of #93928 - nsunderland1:master, r=Mark-Simulacrum
matthiaskrgr Feb 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -156,6 +156,7 @@ Language
- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
- [Allow panicking in constant evaluation.][89508]
- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200]

Compiler
--------
@@ -216,6 +217,9 @@ Cargo
Compatibility notes
-------------------

- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200]
This will break some builds that set `#![deny(dead_code)]`.

Internal changes
----------------
These changes provide no direct user facing benefits, but represent significant
@@ -224,6 +228,7 @@ and related tools.

- [Added an experimental backend for codegen with `libgccjit`.][87260]

[85200]: https://github.com/rust-lang/rust/pull/85200/
[86191]: https://github.com/rust-lang/rust/pull/86191/
[87220]: https://github.com/rust-lang/rust/pull/87220/
[87260]: https://github.com/rust-lang/rust/pull/87260/
4 changes: 4 additions & 0 deletions compiler/rustc_ast_pretty/src/pp/convenience.rs
Original file line number Diff line number Diff line change
@@ -75,6 +75,10 @@ impl Printer {
}

pub fn trailing_comma(&mut self) {
self.scan_break(BreakToken { pre_break: Some(','), ..BreakToken::default() });
}

pub fn trailing_comma_or_space(&mut self) {
self.scan_break(BreakToken {
blank_space: 1,
pre_break: Some(','),
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ impl<'a> State<'a> {
if !field.is_last || has_rest {
self.word_space(",");
} else {
self.trailing_comma();
self.trailing_comma_or_space();
}
}
if has_rest {
48 changes: 34 additions & 14 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::pp::Breaks::Inconsistent;
use crate::pprust::state::{AnnNode, PrintState, State};
use crate::pprust::state::delimited::IterDelimited;
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};

use rustc_ast as ast;
use rustc_ast::GenericBound;
@@ -138,11 +139,10 @@ impl<'a> State<'a> {
self.end(); // end outer head-block
}
ast::ItemKind::Use(ref tree) => {
self.head(visibility_qualified(&item.vis, "use"));
self.print_visibility(&item.vis);
self.word_nbsp("use");
self.print_use_tree(tree);
self.word(";");
self.end(); // end inner head-block
self.end(); // end outer head-block
}
ast::ItemKind::Static(ref ty, mutbl, ref body) => {
let def = ast::Defaultness::Final;
@@ -615,8 +615,8 @@ impl<'a> State<'a> {
ast::UseTreeKind::Simple(rename, ..) => {
self.print_path(&tree.prefix, false, 0);
if let Some(rename) = rename {
self.space();
self.word_space("as");
self.nbsp();
self.word_nbsp("as");
self.print_ident(rename);
}
}
@@ -628,16 +628,36 @@ impl<'a> State<'a> {
self.word("*");
}
ast::UseTreeKind::Nested(ref items) => {
if tree.prefix.segments.is_empty() {
self.word("{");
} else {
if !tree.prefix.segments.is_empty() {
self.print_path(&tree.prefix, false, 0);
self.word("::{");
self.word("::");
}
if items.is_empty() {
self.word("{}");
} else if items.len() == 1 {
self.print_use_tree(&items[0].0);
} else {
self.cbox(INDENT_UNIT);
self.word("{");
self.zerobreak();
self.ibox(0);
for use_tree in items.iter().delimited() {
self.print_use_tree(&use_tree.0);
if !use_tree.is_last {
self.word(",");
if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
self.hardbreak();
} else {
self.space();
}
}
}
self.end();
self.trailing_comma();
self.offset(-INDENT_UNIT);
self.word("}");
self.end();
}
self.commasep(Inconsistent, &items, |this, &(ref tree, _)| {
this.print_use_tree(tree)
});
self.word("}");
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
@@ -97,6 +97,7 @@ E0184: include_str!("./error_codes/E0184.md"),
E0185: include_str!("./error_codes/E0185.md"),
E0186: include_str!("./error_codes/E0186.md"),
E0191: include_str!("./error_codes/E0191.md"),
E0192: include_str!("./error_codes/E0192.md"),
E0193: include_str!("./error_codes/E0193.md"),
E0195: include_str!("./error_codes/E0195.md"),
E0197: include_str!("./error_codes/E0197.md"),
@@ -522,7 +523,6 @@ E0787: include_str!("./error_codes/E0787.md"),
// E0188, // can not cast an immutable reference to a mutable pointer
// E0189, // deprecated: can only cast a boxed pointer to a boxed object
// E0190, // deprecated: can only cast a &-pointer to an &-object
// E0192, // negative impl only applicable to auto traits
// E0194, // merged into E0403
// E0196, // cannot determine a type for this closure
E0208,
6 changes: 4 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0192.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#### Note: this error code is no longer emitted by the compiler.

A negative impl was added on a trait implementation.

Erroneous code example:

```compile_fail,E0192
```compile_fail
trait Trait {
type Bar;
}

struct Foo;

impl !Trait for Foo { } //~ ERROR E0192
impl !Trait for Foo { } //~ ERROR

fn main() {}
```
6 changes: 3 additions & 3 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
@@ -1457,9 +1457,9 @@ impl<'a> Parser<'a> {
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
} else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) {
// We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the
// "must be followed by a colon" error, and the "expected one of" error.
self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly");
// We're probably inside of a `Path<'a>` that needs a turbofish
let msg = "expected `while`, `for`, `loop` or `{` after a label";
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
consume_colon = false;
Ok(self.mk_expr_err(lo))
} else {
23 changes: 23 additions & 0 deletions src/test/pretty/use-tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// pp-exact
// edition:2021

#![allow(unused_imports)]

use ::std::fmt::{self, Debug, Display, Write as _};

use core::option::Option::*;

use core::{
cmp::{Eq, Ord, PartialEq, PartialOrd},
convert::{AsMut, AsRef, From, Into},
iter::{
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator,
IntoIterator, Iterator,
},
marker::{
Copy as Copy, Send as Send, Sized as Sized, Sync as Sync, Unpin as U,
},
ops::{*, Drop, Fn, FnMut, FnOnce},
};

fn main() {}
24 changes: 24 additions & 0 deletions src/test/ui/associated-types/issue-91069.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// check-pass

pub trait Associate {
type Associated;
}

pub struct Wrap<'a> {
pub field: &'a i32,
}

pub trait Create<T> {
fn create() -> Self;
}

pub fn oh_no<'a, T>()
where
Wrap<'a>: Associate,
<Wrap<'a> as Associate>::Associated: Create<T>,
{
<Wrap<'a> as Associate>::Associated::create();
}


pub fn main() {}
17 changes: 17 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-80626.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// check-fail

// This should pass, but it requires `Sized` to be coinductive.

#![feature(generic_associated_types)]

trait Allocator {
type Allocated<T>;
}

enum LinkedList<A: Allocator> {
Head,
Next(A::Allocated<Self>)
//~^ overflow
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-80626.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized`
--> $DIR/issue-80626.rs:13:10
|
LL | Next(A::Allocated<Self>)
| ^^^^^^^^^^^^^^^^^^
|
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | Next(&A::Allocated<Self>)
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | Next(Box<A::Allocated<Self>>)
| ++++ +

error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.
27 changes: 27 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-86218.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// check-fail

// This should pass, but seems to run into a TAIT issue.

#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]

pub trait Stream {
type Item;
}

impl Stream for () {
type Item = i32;
}

trait Yay<AdditionalValue> {
type InnerStream<'s>: Stream<Item = i32> + 's;
fn foo<'s>() -> Self::InnerStream<'s>;
}

impl<'a> Yay<&'a ()> for () {
type InnerStream<'s> = impl Stream<Item = i32> + 's;
//~^ the type
fn foo<'s>() -> Self::InnerStream<'s> { todo!() }
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-86218.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0477]: the type `impl Stream<Item = i32>` does not fulfill the required lifetime
--> $DIR/issue-86218.rs:22:28
|
LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: type must outlive the lifetime `'s` as defined here as required by this binding
--> $DIR/issue-86218.rs:22:22
|
LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
| ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0477`.
45 changes: 45 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87735.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// check-fail

// This should pass, but we need an extension of implied bounds (probably).

#![feature(generic_associated_types)]

pub trait AsRef2 {
type Output<'a> where Self: 'a;

fn as_ref2<'a>(&'a self) -> Self::Output<'a>;
}

impl<T> AsRef2 for Vec<T> {
type Output<'a> where Self: 'a = &'a [T];

fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
&self[..]
}
}

#[derive(Debug)]
struct Foo<T>(T);
#[derive(Debug)]
struct FooRef<'a, U>(&'a [U]);

impl<'b, T, U> AsRef2 for Foo<T> //~ the type parameter
where
// * `for<'b, 'c> T: AsRef2<Output<'b> = &'c [U]>>` does not work
//
// * `U` is unconstrained but should be allowed in this context because `Output` is
// an associated type
T: AsRef2<Output<'b> = &'b [U]>,
U: 'b
{
type Output<'a> where Self: 'a = FooRef<'a, U>;

fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
FooRef(self.0.as_ref2())
}
}

fn main() {
let foo = Foo(vec![1, 2, 3]);
dbg!(foo.as_ref2());
}
9 changes: 9 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87735.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-87735.rs:26:13
|
LL | impl<'b, T, U> AsRef2 for Foo<T>
| ^ unconstrained type parameter

error: aborting due to previous error

For more information about this error, try `rustc --explain E0207`.
22 changes: 22 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87748.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// check-fail

// This should pass, but unnormalized input args aren't treated as implied.

#![feature(generic_associated_types)]

trait MyTrait {
type Assoc<'a, 'b> where 'b: 'a;
fn do_sth(arg: Self::Assoc<'_, '_>);
}

struct Foo;

impl MyTrait for Foo {
type Assoc<'a, 'b> where 'b: 'a = u32;

fn do_sth(_: u32) {} //~ lifetime bound
// fn do_sth(_: Self::Assoc<'static, 'static>) {}
// fn do_sth(_: Self::Assoc<'_, '_>) {}
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87748.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0478]: lifetime bound not satisfied
--> $DIR/issue-87748.rs:17:5
|
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
--> $DIR/issue-87748.rs:17:5
|
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
--> $DIR/issue-87748.rs:17:5
|
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0478`.
21 changes: 21 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87755.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// check-fail

// This should pass.

#![feature(generic_associated_types)]

use std::fmt::Debug;

trait Foo {
type Ass where Self::Ass: Debug;
}

#[derive(Debug)]
struct Bar;

impl Foo for Bar {
type Ass = Bar;
//~^ overflow
}

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87755.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0275]: overflow evaluating the requirement `<Bar as Foo>::Ass == _`
--> $DIR/issue-87755.rs:17:16
|
LL | type Ass = Bar;
| ^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.
26 changes: 26 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87803.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// check-fail

// This should pass, but using a type alias vs a reference directly
// changes late-bound -> early-bound.

#![feature(generic_associated_types)]

trait Scanner {
type Input<'a>;
type Token<'a>;

fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>;
}

struct IdScanner();

impl Scanner for IdScanner {
type Input<'a> = &'a str;
type Token<'a> = &'a str;

fn scan<'a>(&mut self, s : &'a str) -> &'a str { //~ lifetime parameters
s
}
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-87803.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration
--> $DIR/issue-87803.rs:21:12
|
LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>;
| ---- lifetimes in impl do not match this method in trait
...
LL | fn scan<'a>(&mut self, s : &'a str) -> &'a str {
| ^^^^ lifetimes do not match method in trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0195`.
31 changes: 31 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88382.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// check-fail

// This should pass, but has a missed normalization due to HRTB.

#![feature(generic_associated_types)]

trait Iterable {
type Iterator<'a> where Self: 'a;
fn iter(&self) -> Self::Iterator<'_>;
}

struct SomeImplementation();

impl Iterable for SomeImplementation {
type Iterator<'a> = std::iter::Empty<usize>;
fn iter(&self) -> Self::Iterator<'_> {
std::iter::empty()
}
}

fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
f(&mut i.iter());
}

fn main() {
do_something(SomeImplementation(), |_| ());
do_something(SomeImplementation(), test);
//~^ type mismatch
}

fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
20 changes: 20 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88382.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0631]: type mismatch in function arguments
--> $DIR/issue-88382.rs:27:40
|
LL | do_something(SomeImplementation(), test);
| ------------ ^^^^ expected signature of `for<'a> fn(&mut <SomeImplementation as Iterable>::Iterator<'a>) -> _`
| |
| required by a bound introduced by this call
...
LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
| ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
|
note: required by a bound in `do_something`
--> $DIR/issue-88382.rs:21:56
|
LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0631`.
31 changes: 31 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88460.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// check-fail

// This should pass, but has a missed normalization due to HRTB.

#![feature(generic_associated_types)]

pub trait Marker {}

pub trait Trait {
type Assoc<'a>;
}

fn test<T>(value: T)
where
T: Trait,
for<'a> T::Assoc<'a>: Marker,
{
}

impl Marker for () {}

struct Foo;

impl Trait for Foo {
type Assoc<'a> = ();
}

fn main() {
test(Foo);
//~^ the trait bound
}
18 changes: 18 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88460.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
--> $DIR/issue-88460.rs:29:5
|
LL | test(Foo);
| ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
|
note: required by a bound in `test`
--> $DIR/issue-88460.rs:16:27
|
LL | fn test<T>(value: T)
| ---- required by a bound in this
...
LL | for<'a> T::Assoc<'a>: Marker,
| ^^^^^^ required by this bound in `test`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
34 changes: 34 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88526.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// check-fail

// This should pass, but requires more logic.

#![feature(generic_associated_types)]

trait A {
type I<'a>;
}

pub struct TestA<F>
{
f: F,
}

impl<F> A for TestA<F> {
type I<'a> = &'a F;
}

struct TestB<Q, F>
{
q: Q,
f: F,
}

impl<'q, Q, I, F> A for TestB<Q, F> //~ the type parameter
where
Q: A<I<'q> = &'q I>,
F: Fn(I),
{
type I<'a> = ();
}

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-88526.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-88526.rs:26:13
|
LL | impl<'q, Q, I, F> A for TestB<Q, F>
| ^ unconstrained type parameter

error: aborting due to previous error

For more information about this error, try `rustc --explain E0207`.
43 changes: 43 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-89008.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// check-fail
// edition:2021

// This should pass, but seems to run into a TAIT bug.

#![feature(type_alias_impl_trait)]
#![feature(generic_associated_types)]

use std::future::Future;

trait Stream {
type Item;
}

struct Empty<T>(T);
impl<T> Stream for Empty<T> {
type Item = ();
}
fn empty<T>() -> Empty<T> {
todo!()
}

trait X {
type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a;

type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;

fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>;
}

struct Y;

impl X for Y {
type LineStream<'a, Repr> = impl Stream<Item = Repr>; //~ could not find

type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;

fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { //~ type mismatch
async {empty()}
}
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/generic-associated-types/bugs/issue-89008.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == impl Stream<Item = Repr>`
--> $DIR/issue-89008.rs:38:43
|
LL | type LineStream<'a, Repr> = impl Stream<Item = Repr>;
| ------------------------ the expected opaque type
...
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found struct `Empty`
|
= note: expected opaque type `impl Stream<Item = Repr>`
found struct `Empty<_>`

error: could not find defining uses
--> $DIR/issue-89008.rs:34:33
|
LL | type LineStream<'a, Repr> = impl Stream<Item = Repr>;
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
22 changes: 22 additions & 0 deletions src/test/ui/generic-associated-types/issue-91139.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// check-pass

#![feature(generic_associated_types)]

trait Foo<T> {
type Type<'a>
where
T: 'a;
}

impl<T> Foo<T> for () {
type Type<'a>
where
T: 'a,
= ();
}

fn foo<T>() {
let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
}

pub fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/parser/issues/issue-93282.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
fn main() {
f<'a,>
//~^ ERROR expected
//~| ERROR expected
}

fn bar(a: usize, b: usize) -> usize {
a + b
}

fn foo() {
let x = 1;
bar('y, x);
//~^ ERROR expected
}
14 changes: 13 additions & 1 deletion src/test/ui/parser/issues/issue-93282.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/issue-93282.rs:2:9
|
LL | f<'a,>
| ^ expected `while`, `for`, `loop` or `{` after a label

error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `{`, `}`, or an operator, found `,`
--> $DIR/issue-93282.rs:2:9
|
@@ -9,5 +15,11 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum
LL | f::<'a,>
| ++

error: aborting due to previous error
error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/issue-93282.rs:13:11
|
LL | bar('y, x);
| ^ expected `while`, `for`, `loop` or `{` after a label

error: aborting due to 3 previous errors

2 changes: 2 additions & 0 deletions src/test/ui/parser/require-parens-for-chained-comparison.rs
Original file line number Diff line number Diff line change
@@ -22,10 +22,12 @@ fn main() {
let _ = f<'_, i8>();
//~^ ERROR expected one of
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
//~| ERROR expected

f<'_>();
//~^ comparison operators cannot be chained
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
//~| ERROR expected

let _ = f<u8>;
//~^ ERROR comparison operators cannot be chained
18 changes: 15 additions & 3 deletions src/test/ui/parser/require-parens-for-chained-comparison.stderr
Original file line number Diff line number Diff line change
@@ -53,6 +53,12 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum
LL | let _ = f::<u8, i8>();
| ++

error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/require-parens-for-chained-comparison.rs:22:17
|
LL | let _ = f<'_, i8>();
| ^ expected `while`, `for`, `loop` or `{` after a label

error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,`
--> $DIR/require-parens-for-chained-comparison.rs:22:17
|
@@ -64,8 +70,14 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum
LL | let _ = f::<'_, i8>();
| ++

error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/require-parens-for-chained-comparison.rs:27:9
|
LL | f<'_>();
| ^ expected `while`, `for`, `loop` or `{` after a label

error: comparison operators cannot be chained
--> $DIR/require-parens-for-chained-comparison.rs:26:6
--> $DIR/require-parens-for-chained-comparison.rs:27:6
|
LL | f<'_>();
| ^ ^
@@ -76,13 +88,13 @@ LL | f::<'_>();
| ++

error: comparison operators cannot be chained
--> $DIR/require-parens-for-chained-comparison.rs:30:14
--> $DIR/require-parens-for-chained-comparison.rs:32:14
|
LL | let _ = f<u8>;
| ^ ^
|
= help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
= help: or use `(...)` if you meant to specify fn arguments

error: aborting due to 8 previous errors
error: aborting due to 10 previous errors

5 changes: 3 additions & 2 deletions src/tools/linkchecker/main.rs
Original file line number Diff line number Diff line change
@@ -182,8 +182,9 @@ impl Checker {
fn walk(&mut self, dir: &Path, report: &mut Report) {
for entry in t!(dir.read_dir()).map(|e| t!(e)) {
let path = entry.path();
let kind = t!(entry.file_type());
if kind.is_dir() {
// Goes through symlinks
let metadata = t!(fs::metadata(&path));
if metadata.is_dir() {
self.walk(&path, report);
} else {
self.check(&path, report);
33 changes: 29 additions & 4 deletions src/tools/tidy/src/error_codes_check.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::fs::read_to_string;
use std::path::Path;
@@ -205,6 +205,7 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
let mut found_explanations = 0;
let mut found_tests = 0;
let mut error_codes: HashMap<String, ErrorCodeStatus> = HashMap::new();
let mut explanations: HashSet<String> = HashSet::new();
// We want error codes which match the following cases:
//
// * foo(a, E0111, a)
@@ -218,17 +219,27 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
for path in paths {
super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| {
let file_name = entry.file_name();
let entry_path = entry.path();

if file_name == "error_codes.rs" {
extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors);
found_explanations += 1;
} else if entry.path().extension() == Some(OsStr::new("stderr")) {
} else if entry_path.extension() == Some(OsStr::new("stderr")) {
extract_error_codes_from_tests(contents, &mut error_codes);
found_tests += 1;
} else if entry.path().extension() == Some(OsStr::new("rs")) {
} else if entry_path.extension() == Some(OsStr::new("rs")) {
let path = entry.path().to_string_lossy();
if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) {
extract_error_codes_from_source(contents, &mut error_codes, &regex);
}
} else if entry_path
.parent()
.and_then(|p| p.file_name())
.map(|p| p == "error_codes")
.unwrap_or(false)
&& entry_path.extension() == Some(OsStr::new("md"))
{
explanations.insert(file_name.to_str().unwrap().replace(".md", ""));
}
});
}
@@ -240,6 +251,10 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
eprintln!("No error code was found in compilation errors!");
*bad = true;
}
if explanations.is_empty() {
eprintln!("No error code explanation was found!");
*bad = true;
}
if errors.is_empty() {
println!("Found {} error codes", error_codes.len());

@@ -282,11 +297,21 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
}
}
}
if errors.is_empty() {
for explanation in explanations {
if !error_codes.contains_key(&explanation) {
errors.push(format!(
"{} error code explanation should be listed in `error_codes.rs`",
explanation
));
}
}
}
errors.sort();
for err in &errors {
eprintln!("{}", err);
}
println!("Found {} error codes with no tests", errors.len());
println!("Found {} error(s) in error codes", errors.len());
if !errors.is_empty() {
*bad = true;
}