Auto merge of #93933 - matthiaskrgr:rollup-1hjae6g, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #91908 (Add 2 tests) - #93595 (fix ICE when parsing lifetime as function argument) - #93757 (Add some known GAT bugs as tests) - #93759 (Pretty print ItemKind::Use in rustfmt style) - #93897 (linkchecker: fix panic on directory symlinks) - #93898 (tidy: Extend error code check) - #93928 (Add missing release notes for #85200) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f8f175199e
36 changed files with 644 additions and 31 deletions
|
@ -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/
|
||||
|
|
|
@ -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(','),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {}
|
||||
```
|
||||
|
|
|
@ -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
src/test/pretty/use-tree.rs
Normal file
23
src/test/pretty/use-tree.rs
Normal file
|
@ -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
src/test/ui/associated-types/issue-91069.rs
Normal file
24
src/test/ui/associated-types/issue-91069.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-80626.rs
Normal file
17
src/test/ui/generic-associated-types/bugs/issue-80626.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-80626.stderr
Normal file
20
src/test/ui/generic-associated-types/bugs/issue-80626.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-86218.rs
Normal file
27
src/test/ui/generic-associated-types/bugs/issue-86218.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-86218.stderr
Normal file
15
src/test/ui/generic-associated-types/bugs/issue-86218.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87735.rs
Normal file
45
src/test/ui/generic-associated-types/bugs/issue-87735.rs
Normal file
|
@ -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());
|
||||
}
|
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87748.rs
Normal file
22
src/test/ui/generic-associated-types/bugs/issue-87748.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87748.stderr
Normal file
20
src/test/ui/generic-associated-types/bugs/issue-87748.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87755.rs
Normal file
21
src/test/ui/generic-associated-types/bugs/issue-87755.rs
Normal file
|
@ -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() {}
|
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87803.rs
Normal file
26
src/test/ui/generic-associated-types/bugs/issue-87803.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-87803.stderr
Normal file
12
src/test/ui/generic-associated-types/bugs/issue-87803.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-88382.rs
Normal file
31
src/test/ui/generic-associated-types/bugs/issue-88382.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-88382.stderr
Normal file
20
src/test/ui/generic-associated-types/bugs/issue-88382.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-88460.rs
Normal file
31
src/test/ui/generic-associated-types/bugs/issue-88460.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-88460.stderr
Normal file
18
src/test/ui/generic-associated-types/bugs/issue-88460.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-88526.rs
Normal file
34
src/test/ui/generic-associated-types/bugs/issue-88526.rs
Normal file
|
@ -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() {}
|
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-89008.rs
Normal file
43
src/test/ui/generic-associated-types/bugs/issue-89008.rs
Normal file
|
@ -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
src/test/ui/generic-associated-types/bugs/issue-89008.stderr
Normal file
21
src/test/ui/generic-associated-types/bugs/issue-89008.stderr
Normal file
|
@ -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
src/test/ui/generic-associated-types/issue-91139.rs
Normal file
22
src/test/ui/generic-associated-types/issue-91139.rs
Normal file
|
@ -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() {}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,7 +88,7 @@ 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>;
|
||||
| ^ ^
|
||||
|
@ -84,5 +96,5 @@ 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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®ex);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue