Avoid an empty trait name in impl blocks.
`resolve_ident_in_lexical_scope` checks for an empty name. Why is this necessary? Because `parse_item_impl` can produce an `impl` block with an empty trait name in some cases. This is pretty gross and very non-obvious. This commit avoids the use of the empty trait name. In one case the trait name is instead pulled from `TyKind::ImplTrait`, which prevents the output for `tests/ui/impl-trait/extra-impl-in-trait-impl.rs` from changing. In the other case we just fail the parse and don't try to recover. I think losing error recovery in this obscure case is worth the code cleanup. This change affects `tests/ui/parser/impl-parsing.rs`, which is split in two, and the obsolete `..` syntax cases are removed (they are tested elsewhere).
This commit is contained in:
parent
f419b18d16
commit
7ae5c7f32d
6 changed files with 29 additions and 47 deletions
|
@ -649,6 +649,7 @@ impl<'a> Parser<'a> {
|
|||
other => {
|
||||
if let TyKind::ImplTrait(_, bounds) = other
|
||||
&& let [bound] = bounds.as_slice()
|
||||
&& let GenericBound::Trait(poly_trait_ref) = bound
|
||||
{
|
||||
// Suggest removing extra `impl` keyword:
|
||||
// `impl<T: Default> impl Default for Wrapper<T>`
|
||||
|
@ -658,12 +659,12 @@ impl<'a> Parser<'a> {
|
|||
extra_impl_kw,
|
||||
impl_trait_span: ty_first.span,
|
||||
});
|
||||
poly_trait_ref.trait_ref.path.clone()
|
||||
} else {
|
||||
self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType {
|
||||
span: ty_first.span,
|
||||
});
|
||||
return Err(self.dcx().create_err(
|
||||
errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
|
||||
));
|
||||
}
|
||||
ast::Path::from_ident(Ident::new(kw::Empty, ty_first.span))
|
||||
}
|
||||
};
|
||||
let trait_ref = TraitRef { path, ref_id: ty_first.id };
|
||||
|
|
|
@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
) -> Option<LexicalScopeBinding<'ra>> {
|
||||
assert!(ns == TypeNS || ns == ValueNS);
|
||||
let orig_ident = ident;
|
||||
if ident.name == kw::Empty {
|
||||
return Some(LexicalScopeBinding::Res(Res::Err));
|
||||
}
|
||||
let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
|
||||
// FIXME(jseyfried) improve `Self` hygiene
|
||||
let empty_span = ident.span.with_ctxt(SyntaxContext::root());
|
||||
|
|
4
tests/ui/parser/impl-parsing-2.rs
Normal file
4
tests/ui/parser/impl-parsing-2.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
impl ! {} // OK
|
||||
|
||||
default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
|
||||
//~^ ERROR `default` is not followed by an item
|
18
tests/ui/parser/impl-parsing-2.stderr
Normal file
18
tests/ui/parser/impl-parsing-2.stderr
Normal file
|
@ -0,0 +1,18 @@
|
|||
error: `default` is not followed by an item
|
||||
--> $DIR/impl-parsing-2.rs:3:1
|
||||
|
|
||||
LL | default unsafe FAIL
|
||||
| ^^^^^^^ the `default` qualifier
|
||||
|
|
||||
= note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
|
||||
|
||||
error: expected item, found keyword `unsafe`
|
||||
--> $DIR/impl-parsing-2.rs:3:9
|
||||
|
|
||||
LL | default unsafe FAIL
|
||||
| ^^^^^^ expected item
|
||||
|
|
||||
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -2,9 +2,4 @@ impl ! {} // OK
|
|||
impl ! where u8: Copy {} // OK
|
||||
|
||||
impl Trait Type {} //~ ERROR missing `for` in a trait impl
|
||||
impl Trait .. {} //~ ERROR missing `for` in a trait impl
|
||||
impl ?Sized for Type {} //~ ERROR expected a trait, found type
|
||||
impl ?Sized for .. {} //~ ERROR expected a trait, found type
|
||||
|
||||
default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
|
||||
//~^ ERROR `default` is not followed by an item
|
||||
|
|
|
@ -9,44 +9,11 @@ help: add `for` here
|
|||
LL | impl Trait for Type {}
|
||||
| +++
|
||||
|
||||
error: missing `for` in a trait impl
|
||||
--> $DIR/impl-parsing.rs:5:11
|
||||
|
|
||||
LL | impl Trait .. {}
|
||||
| ^
|
||||
|
|
||||
help: add `for` here
|
||||
|
|
||||
LL | impl Trait for .. {}
|
||||
| +++
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/impl-parsing.rs:6:6
|
||||
--> $DIR/impl-parsing.rs:5:6
|
||||
|
|
||||
LL | impl ?Sized for Type {}
|
||||
| ^^^^^^
|
||||
|
||||
error: expected a trait, found type
|
||||
--> $DIR/impl-parsing.rs:7:6
|
||||
|
|
||||
LL | impl ?Sized for .. {}
|
||||
| ^^^^^^
|
||||
|
||||
error: `default` is not followed by an item
|
||||
--> $DIR/impl-parsing.rs:9:1
|
||||
|
|
||||
LL | default unsafe FAIL
|
||||
| ^^^^^^^ the `default` qualifier
|
||||
|
|
||||
= note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
|
||||
|
||||
error: expected item, found keyword `unsafe`
|
||||
--> $DIR/impl-parsing.rs:9:9
|
||||
|
|
||||
LL | default unsafe FAIL
|
||||
| ^^^^^^ expected item
|
||||
|
|
||||
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue