mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
make error emitted on impl &Trait
nicer
This commit is contained in:
parent
ca5d92d789
commit
e590b93499
@ -2032,7 +2032,8 @@ impl Clone for Ty {
|
||||
impl Ty {
|
||||
pub fn peel_refs(&self) -> &Self {
|
||||
let mut final_ty = self;
|
||||
while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
|
||||
while let TyKind::Ref(_, MutTy { ty, .. }) | TyKind::Ptr(MutTy { ty, .. }) = &final_ty.kind
|
||||
{
|
||||
final_ty = ty;
|
||||
}
|
||||
final_ty
|
||||
|
@ -727,11 +727,13 @@ impl<'a> Parser<'a> {
|
||||
let mut bounds = Vec::new();
|
||||
let mut negative_bounds = Vec::new();
|
||||
|
||||
// In addition to looping while we find generic bounds:
|
||||
// We continue even if we find a keyword. This is necessary for error recovery on,
|
||||
// for example, `impl fn()`. The only keyword that can go after generic bounds is
|
||||
// `where`, so stop if it's it.
|
||||
// We also continue if we find types (not traits), again for error recovery.
|
||||
while self.can_begin_bound()
|
||||
// Continue even if we find a keyword.
|
||||
// This is necessary for error recover on, for example, `impl fn()`.
|
||||
//
|
||||
// The only keyword that can go after generic bounds is `where`, so stop if it's it.
|
||||
|| self.token.can_begin_type()
|
||||
|| (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
|
||||
{
|
||||
if self.token.is_keyword(kw::Dyn) {
|
||||
@ -938,6 +940,35 @@ impl<'a> Parser<'a> {
|
||||
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
|
||||
&& let Some(path) = self.recover_path_from_fn()
|
||||
{
|
||||
path
|
||||
} else if !self.token.is_path_start() && self.token.can_begin_type() && let Ok(ty) = self.parse_ty_no_plus() {
|
||||
// Instead of finding a path (a trait), we found a type.
|
||||
let mut err = self.struct_span_err(ty.span, "expected a trait, found type");
|
||||
|
||||
// If we can recover, try to extract a path from the type. Note
|
||||
// that we do not use the try operator when parsing the type because
|
||||
// if it fails then we get a parser error which we don't want (we're trying
|
||||
// to recover from errors, not make more).
|
||||
let path = if self.may_recover()
|
||||
&& matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..))
|
||||
&& let TyKind::Path(_, path) = &ty.peel_refs().kind {
|
||||
// Just get the indirection part of the type.
|
||||
let span = ty.span.until(path.span);
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"consider removing the indirection",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
path.clone()
|
||||
} else {
|
||||
return Err(err);
|
||||
};
|
||||
|
||||
err.emit();
|
||||
|
||||
path
|
||||
} else {
|
||||
self.parse_path(PathStyle::Type)?
|
||||
|
24
tests/ui/generics/issue-106694.rs
Normal file
24
tests/ui/generics/issue-106694.rs
Normal file
@ -0,0 +1,24 @@
|
||||
trait Trait {}
|
||||
|
||||
fn foo(_: impl &Trait) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
|
||||
fn bar<T: &Trait>(_: T) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
|
||||
fn partially_correct_impl(_: impl &*const &Trait + Copy) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
|
||||
fn foo_bad(_: impl &BadTrait) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
//~^^ ERROR cannot find trait `BadTrait` in this scope
|
||||
|
||||
fn bar_bad<T: &BadTrait>(_: T) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
//~^^ ERROR cannot find trait `BadTrait` in this scope
|
||||
|
||||
fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {}
|
||||
//~^ ERROR expected a trait, found type
|
||||
//~^^ ERROR cannot find trait `BadTrait` in this scope
|
||||
|
||||
fn main() {}
|
93
tests/ui/generics/issue-106694.stderr
Normal file
93
tests/ui/generics/issue-106694.stderr
Normal file
@ -0,0 +1,93 @@
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:3:16
|
||||
|
|
||||
LL | fn foo(_: impl &Trait) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn foo(_: impl &Trait) {}
|
||||
LL + fn foo(_: impl Trait) {}
|
||||
|
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:6:11
|
||||
|
|
||||
LL | fn bar<T: &Trait>(_: T) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn bar<T: &Trait>(_: T) {}
|
||||
LL + fn bar<T: Trait>(_: T) {}
|
||||
|
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:9:35
|
||||
|
|
||||
LL | fn partially_correct_impl(_: impl &*const &Trait + Copy) {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn partially_correct_impl(_: impl &*const &Trait + Copy) {}
|
||||
LL + fn partially_correct_impl(_: impl Trait + Copy) {}
|
||||
|
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:12:20
|
||||
|
|
||||
LL | fn foo_bad(_: impl &BadTrait) {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn foo_bad(_: impl &BadTrait) {}
|
||||
LL + fn foo_bad(_: impl BadTrait) {}
|
||||
|
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:16:15
|
||||
|
|
||||
LL | fn bar_bad<T: &BadTrait>(_: T) {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn bar_bad<T: &BadTrait>(_: T) {}
|
||||
LL + fn bar_bad<T: BadTrait>(_: T) {}
|
||||
|
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/issue-106694.rs:20:39
|
||||
|
|
||||
LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider removing the indirection
|
||||
|
|
||||
LL - fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {}
|
||||
LL + fn partially_correct_impl_bad(_: impl BadTrait + Copy) {}
|
||||
|
|
||||
|
||||
error[E0405]: cannot find trait `BadTrait` in this scope
|
||||
--> $DIR/issue-106694.rs:12:21
|
||||
|
|
||||
LL | fn foo_bad(_: impl &BadTrait) {}
|
||||
| ^^^^^^^^ not found in this scope
|
||||
|
||||
error[E0405]: cannot find trait `BadTrait` in this scope
|
||||
--> $DIR/issue-106694.rs:16:16
|
||||
|
|
||||
LL | fn bar_bad<T: &BadTrait>(_: T) {}
|
||||
| ^^^^^^^^ not found in this scope
|
||||
|
||||
error[E0405]: cannot find trait `BadTrait` in this scope
|
||||
--> $DIR/issue-106694.rs:20:48
|
||||
|
|
||||
LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {}
|
||||
| ^^^^^^^^ not found in this scope
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0405`.
|
Loading…
Reference in New Issue
Block a user