Auto merge of #104102 - Dylan-DPC:rollup-0eakshe, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #103757 (Mention const and lifetime parameters in error E0207) - #103986 (Don't silently eat label before block in block-like expr) - #104003 (Move some tests to more reasonable directories) - #104038 (Normalize types when deducing closure signature from supertraits) - #104052 (Fix `resolution_failure` ICE) - #104090 (Modify comment syntax error) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
68f77297c0
@ -1,4 +1,5 @@
|
||||
A type parameter that is specified for `impl` is not constrained.
|
||||
A type, const or lifetime parameter that is specified for `impl` is not
|
||||
constrained.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
@ -14,8 +15,8 @@ impl<T: Default> Foo {
|
||||
}
|
||||
```
|
||||
|
||||
Any type parameter of an `impl` must meet at least one of
|
||||
the following criteria:
|
||||
Any type or const parameter of an `impl` must meet at least one of the
|
||||
following criteria:
|
||||
|
||||
- it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>`
|
||||
- for a trait impl, it appears in the _implemented trait_, e.g.
|
||||
@ -23,6 +24,9 @@ the following criteria:
|
||||
- it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T
|
||||
where T: AnotherTrait<AssocType=U>`
|
||||
|
||||
Any unconstrained lifetime parameter of an `impl` is not supported if the
|
||||
lifetime parameter is used by an associated type.
|
||||
|
||||
### Error example 1
|
||||
|
||||
Suppose we have a struct `Foo` and we would like to define some methods for it.
|
||||
@ -32,7 +36,6 @@ The problem is that the parameter `T` does not appear in the implementing type
|
||||
(`Foo`) of the impl. In this case, we can fix the error by moving the type
|
||||
parameter from the `impl` to the method `get`:
|
||||
|
||||
|
||||
```
|
||||
struct Foo;
|
||||
|
||||
@ -128,6 +131,70 @@ impl<T: Default> Maker<Foo<T>> for FooMaker {
|
||||
}
|
||||
```
|
||||
|
||||
### Error example 3
|
||||
|
||||
Suppose we have a struct `Foo` and we would like to define some methods for it.
|
||||
The following code example has a definition which leads to a compiler error:
|
||||
|
||||
```compile_fail,E0207
|
||||
struct Foo;
|
||||
|
||||
impl<const T: i32> Foo {
|
||||
// error: the const parameter `T` is not constrained by the impl trait, self
|
||||
// type, or predicates [E0207]
|
||||
fn get(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The problem is that the const parameter `T` does not appear in the implementing
|
||||
type (`Foo`) of the impl. In this case, we can fix the error by moving the type
|
||||
parameter from the `impl` to the method `get`:
|
||||
|
||||
|
||||
```
|
||||
struct Foo;
|
||||
|
||||
// Move the const parameter from the impl to the method
|
||||
impl Foo {
|
||||
fn get<const T: i32>(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error example 4
|
||||
|
||||
Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We
|
||||
would like to implement trait `Contains` for `Foo`. The trait `Contains` have
|
||||
the associated type `B`. The following code example has a definition which
|
||||
leads to a compiler error:
|
||||
|
||||
```compile_fail,E0207
|
||||
struct Foo;
|
||||
struct Bar<'a>;
|
||||
|
||||
trait Contains {
|
||||
type B;
|
||||
|
||||
fn get(&self) -> i32;
|
||||
}
|
||||
|
||||
impl<'a> Contains for Foo {
|
||||
type B = Bar<'a>;
|
||||
|
||||
// error: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
// self type, or predicates [E0207]
|
||||
fn get(&self) -> i32 {
|
||||
i32::default()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please note that unconstrained lifetime parameters are not supported if they are
|
||||
being used by an associated type.
|
||||
|
||||
### Additional information
|
||||
|
||||
For more information, please see [RFC 447].
|
||||
|
@ -10,6 +10,7 @@ use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_infer::infer::{InferOk, InferResult};
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
@ -22,7 +23,7 @@ use std::cmp;
|
||||
use std::iter;
|
||||
|
||||
/// What signature do we *expect* the closure to have from context?
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
|
||||
struct ExpectedSig<'tcx> {
|
||||
/// Span that gave us this expectation, if we know that.
|
||||
cause_span: Option<Span>,
|
||||
@ -241,9 +242,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if expected_sig.is_none()
|
||||
&& let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
|
||||
{
|
||||
expected_sig = self.deduce_sig_from_projection(
|
||||
expected_sig = self.normalize_associated_types_in(
|
||||
obligation.cause.span,
|
||||
self.deduce_sig_from_projection(
|
||||
Some(obligation.cause.span),
|
||||
bound_predicate.rebind(proj_predicate),
|
||||
bound_predicate.rebind(proj_predicate),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration
|
||||
/// Emit an error diagnostic for an invalid attribute (optionally performing additional decoration
|
||||
/// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
|
||||
///
|
||||
/// For methods that return a `Result<_, DiagnosticDeriveError>`:
|
||||
@ -126,7 +126,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a error diagnostic for an invalid nested attribute (optionally performing additional
|
||||
/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional
|
||||
/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
|
||||
///
|
||||
/// For methods that return a `Result<_, DiagnosticDeriveError>`:
|
||||
|
@ -2468,11 +2468,15 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool {
|
||||
let Some(label) = self.eat_label().filter(|_| {
|
||||
self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace)
|
||||
}) else {
|
||||
// Check for `'a : {`
|
||||
if !(self.check_lifetime()
|
||||
&& self.look_ahead(1, |tok| tok.kind == token::Colon)
|
||||
&& self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace)))
|
||||
{
|
||||
return false;
|
||||
};
|
||||
}
|
||||
let label = self.eat_label().expect("just checked if a label exists");
|
||||
self.bump(); // eat `:`
|
||||
let span = label.ident.span.to(self.prev_token.span);
|
||||
let mut err = self.struct_span_err(span, "block label not supported here");
|
||||
err.span_label(span, "not supported here");
|
||||
|
@ -139,7 +139,7 @@ impl Display for TryReserveError {
|
||||
" because the computed capacity exceeded the collection's maximum"
|
||||
}
|
||||
TryReserveErrorKind::AllocError { .. } => {
|
||||
" because the memory allocator returned a error"
|
||||
" because the memory allocator returned an error"
|
||||
}
|
||||
};
|
||||
fmt.write_str(reason)
|
||||
|
@ -402,6 +402,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||
})
|
||||
.and_then(|self_id| match tcx.def_kind(self_id) {
|
||||
DefKind::Impl => self.def_id_to_res(self_id),
|
||||
DefKind::Use => None,
|
||||
def_kind => Some(Res::Def(def_kind, self_id)),
|
||||
})
|
||||
}
|
||||
@ -1772,7 +1773,6 @@ fn resolution_failure(
|
||||
|
||||
// Otherwise, it must be an associated item or variant
|
||||
let res = partial_res.expect("None case was handled by `last_found_module`");
|
||||
let name = res.name(tcx);
|
||||
let kind = match res {
|
||||
Res::Def(kind, _) => Some(kind),
|
||||
Res::Primitive(_) => None,
|
||||
@ -1814,6 +1814,7 @@ fn resolution_failure(
|
||||
} else {
|
||||
"associated item"
|
||||
};
|
||||
let name = res.name(tcx);
|
||||
let note = format!(
|
||||
"the {} `{}` has no {} named `{}`",
|
||||
res.descr(),
|
||||
|
6
src/test/rustdoc-ui/issue-103997.rs
Normal file
6
src/test/rustdoc-ui/issue-103997.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// check-pass
|
||||
|
||||
pub fn foo() {}
|
||||
|
||||
/// [`foo`](Self::foo) //~ WARNING unresolved link to `Self::foo`
|
||||
pub use foo as bar;
|
10
src/test/rustdoc-ui/issue-103997.stderr
Normal file
10
src/test/rustdoc-ui/issue-103997.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
warning: unresolved link to `Self::foo`
|
||||
--> $DIR/issue-103997.rs:5:13
|
||||
|
|
||||
LL | /// [`foo`](Self::foo)
|
||||
| ^^^^^^^^^ no item named `Self` in scope
|
||||
|
|
||||
= note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
17
src/test/ui/closures/supertrait-hint-references-assoc-ty.rs
Normal file
17
src/test/ui/closures/supertrait-hint-references-assoc-ty.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// check-pass
|
||||
|
||||
pub trait Fn0: Fn(i32) -> Self::Out {
|
||||
type Out;
|
||||
}
|
||||
|
||||
impl<F: Fn(i32) -> ()> Fn0 for F {
|
||||
type Out = ();
|
||||
}
|
||||
|
||||
pub fn closure_typer(_: impl Fn0) {}
|
||||
|
||||
fn main() {
|
||||
closure_typer(move |x| {
|
||||
let _: i64 = x.into();
|
||||
});
|
||||
}
|
@ -46,7 +46,7 @@ const C: bool = true;
|
||||
trait Trait {}
|
||||
impl dyn Trait { fn existing() {} }
|
||||
|
||||
// FIXME: Should be a error for edition > 2015
|
||||
// FIXME: Should be an error for edition > 2015
|
||||
#[cfg_accessible(Trait::existing)] //~ ERROR not sure
|
||||
const A: bool = true;
|
||||
#[cfg_accessible(Trait::unresolved)] //~ ERROR not sure
|
||||
|
43
src/test/ui/parser/label-after-block-like.rs
Normal file
43
src/test/ui/parser/label-after-block-like.rs
Normal file
@ -0,0 +1,43 @@
|
||||
fn a() {
|
||||
if let () = () 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn b() {
|
||||
if true 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn c() {
|
||||
loop 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn d() {
|
||||
while true 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn e() {
|
||||
while let () = () 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn f() {
|
||||
for _ in 0..0 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn g() {
|
||||
unsafe 'a {}
|
||||
//~^ ERROR labeled expression must be followed by `:`
|
||||
//~| ERROR expected `{`, found `'a`
|
||||
}
|
||||
|
||||
fn main() {}
|
176
src/test/ui/parser/label-after-block-like.stderr
Normal file
176
src/test/ui/parser/label-after-block-like.stderr
Normal file
@ -0,0 +1,176 @@
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:2:20
|
||||
|
|
||||
LL | if let () = () 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:2:20
|
||||
|
|
||||
LL | if let () = () 'a {}
|
||||
| ^^ expected `{`
|
||||
|
|
||||
note: the `if` expression is missing a block after this condition
|
||||
--> $DIR/label-after-block-like.rs:2:8
|
||||
|
|
||||
LL | if let () = () 'a {}
|
||||
| ^^^^^^^^^^^
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | if let () = () { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:8:13
|
||||
|
|
||||
LL | if true 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:8:13
|
||||
|
|
||||
LL | if true 'a {}
|
||||
| ^^ expected `{`
|
||||
|
|
||||
note: the `if` expression is missing a block after this condition
|
||||
--> $DIR/label-after-block-like.rs:8:8
|
||||
|
|
||||
LL | if true 'a {}
|
||||
| ^^^^
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | if true { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:14:10
|
||||
|
|
||||
LL | loop 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:14:10
|
||||
|
|
||||
LL | loop 'a {}
|
||||
| ---- ^^ expected `{`
|
||||
| |
|
||||
| while parsing this `loop` expression
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | loop { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:20:16
|
||||
|
|
||||
LL | while true 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:20:16
|
||||
|
|
||||
LL | while true 'a {}
|
||||
| ----- ---- ^^ expected `{`
|
||||
| | |
|
||||
| | this `while` condition successfully parsed
|
||||
| while parsing the body of this `while` expression
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | while true { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:26:23
|
||||
|
|
||||
LL | while let () = () 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:26:23
|
||||
|
|
||||
LL | while let () = () 'a {}
|
||||
| ----- ----------- ^^ expected `{`
|
||||
| | |
|
||||
| | this `while` condition successfully parsed
|
||||
| while parsing the body of this `while` expression
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | while let () = () { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:32:19
|
||||
|
|
||||
LL | for _ in 0..0 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:32:19
|
||||
|
|
||||
LL | for _ in 0..0 'a {}
|
||||
| ^^ expected `{`
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | for _ in 0..0 { 'a {} }
|
||||
| + +
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/label-after-block-like.rs:38:12
|
||||
|
|
||||
LL | unsafe 'a {}
|
||||
| ---^^
|
||||
| | |
|
||||
| | help: add `:` after the label
|
||||
| the label
|
||||
|
|
||||
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
|
||||
|
||||
error: expected `{`, found `'a`
|
||||
--> $DIR/label-after-block-like.rs:38:12
|
||||
|
|
||||
LL | unsafe 'a {}
|
||||
| ------ ^^ expected `{`
|
||||
| |
|
||||
| while parsing this `unsafe` expression
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | unsafe { 'a {} }
|
||||
| + +
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
@ -9,8 +9,8 @@ use std::path::Path;
|
||||
|
||||
const ENTRY_LIMIT: usize = 1000;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
const ROOT_ENTRY_LIMIT: usize = 941;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 2117;
|
||||
const ROOT_ENTRY_LIMIT: usize = 939;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 2105;
|
||||
|
||||
fn check_entries(path: &Path, bad: &mut bool) {
|
||||
for dir in Walk::new(&path.join("test/ui")) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user