syntax: Rewrite parsing of impls
Properly parse impls for the never type `!` Recover from missing `for` in `impl Trait for Type` Prohibit inherent default impls and default impls of auto traits Change wording in more diagnostics to use "auto traits" Some minor code cleanups in the parser
This commit is contained in:
parent
48ab4cde54
commit
d19e4c4a85
23 changed files with 335 additions and 279 deletions
|
@ -1502,8 +1502,8 @@ impl<'a> LoweringContext<'a> {
|
||||||
fn_def_id: Option<DefId>,
|
fn_def_id: Option<DefId>,
|
||||||
impl_trait_return_allow: bool)
|
impl_trait_return_allow: bool)
|
||||||
-> P<hir::FnDecl> {
|
-> P<hir::FnDecl> {
|
||||||
// NOTE: The two last paramters here have to do with impl Trait. If fn_def_id is Some,
|
// NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
|
||||||
// then impl Trait arguments are lowered into generic paramters on the given
|
// then impl Trait arguments are lowered into generic parameters on the given
|
||||||
// fn_def_id, otherwise impl Trait is disallowed. (for now)
|
// fn_def_id, otherwise impl Trait is disallowed. (for now)
|
||||||
//
|
//
|
||||||
// Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
|
// Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
|
||||||
|
|
|
@ -215,13 +215,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'a Item) {
|
fn visit_item(&mut self, item: &'a Item) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemKind::Impl(.., Some(..), ref ty, ref impl_items) => {
|
ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
|
||||||
self.invalid_visibility(&item.vis, item.span, None);
|
self.invalid_visibility(&item.vis, item.span, None);
|
||||||
if ty.node == TyKind::Err {
|
if ty.node == TyKind::Err {
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
.struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
|
.struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
|
||||||
.help("use `auto trait Trait {}` instead").emit();
|
.help("use `auto trait Trait {}` instead").emit();
|
||||||
}
|
}
|
||||||
|
if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
|
||||||
|
span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
|
||||||
|
}
|
||||||
for impl_item in impl_items {
|
for impl_item in impl_items {
|
||||||
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
|
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
|
||||||
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||||
|
@ -229,10 +232,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Impl(.., None, _, _) => {
|
ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
|
||||||
self.invalid_visibility(&item.vis,
|
self.invalid_visibility(&item.vis,
|
||||||
item.span,
|
item.span,
|
||||||
Some("place qualifiers on individual impl items instead"));
|
Some("place qualifiers on individual impl items instead"));
|
||||||
|
if unsafety == Unsafety::Unsafe {
|
||||||
|
span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
|
||||||
|
}
|
||||||
|
if polarity == ImplPolarity::Negative {
|
||||||
|
self.err_handler().span_err(item.span, "inherent impls cannot be negative");
|
||||||
|
}
|
||||||
|
if defaultness == Defaultness::Default {
|
||||||
|
self.err_handler().span_err(item.span, "inherent impls cannot be default");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemKind::ForeignMod(..) => {
|
ItemKind::ForeignMod(..) => {
|
||||||
self.invalid_visibility(&item.vis,
|
self.invalid_visibility(&item.vis,
|
||||||
|
|
|
@ -82,6 +82,52 @@ extern {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0197: r##"
|
||||||
|
Inherent implementations (one that do not implement a trait but provide
|
||||||
|
methods associated with a type) are always safe because they are not
|
||||||
|
implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
|
||||||
|
implementation will resolve this error.
|
||||||
|
|
||||||
|
```compile_fail,E0197
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
// this will cause this error
|
||||||
|
unsafe impl Foo { }
|
||||||
|
// converting it to this will fix it
|
||||||
|
impl Foo { }
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0198: r##"
|
||||||
|
A negative implementation is one that excludes a type from implementing a
|
||||||
|
particular trait. Not being able to use a trait is always a safe operation,
|
||||||
|
so negative implementations are always safe and never need to be marked as
|
||||||
|
unsafe.
|
||||||
|
|
||||||
|
```compile_fail
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
// unsafe is unnecessary
|
||||||
|
unsafe impl !Clone for Foo { }
|
||||||
|
```
|
||||||
|
|
||||||
|
This will compile:
|
||||||
|
|
||||||
|
```ignore (ignore auto_trait future compatibility warning)
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
auto trait Enterprise {}
|
||||||
|
|
||||||
|
impl !Enterprise for Foo { }
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that negative impls are only allowed for auto traits.
|
||||||
|
"##,
|
||||||
|
|
||||||
E0265: r##"
|
E0265: r##"
|
||||||
This error indicates that a static or constant references itself.
|
This error indicates that a static or constant references itself.
|
||||||
All statics and constants need to resolve to a value in an acyclic manner.
|
All statics and constants need to resolve to a value in an acyclic manner.
|
||||||
|
|
|
@ -107,16 +107,21 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||||
//
|
//
|
||||||
// won't be allowed unless there's an *explicit* implementation of `Send`
|
// won't be allowed unless there's an *explicit* implementation of `Send`
|
||||||
// for `T`
|
// for `T`
|
||||||
hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
|
hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
|
||||||
ref trait_ref, ref self_ty, _) => {
|
let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
|
||||||
self.check_impl(item, self_ty, trait_ref);
|
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
|
||||||
}
|
if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
|
||||||
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
|
tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
|
||||||
// FIXME(#27579) what amount of WF checking do we need for neg impls?
|
}
|
||||||
|
if polarity == hir::ImplPolarity::Positive {
|
||||||
let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
|
self.check_impl(item, self_ty, trait_ref);
|
||||||
if !tcx.trait_is_auto(trait_ref.def_id) {
|
} else {
|
||||||
error_192(tcx, item.span);
|
// FIXME(#27579) what amount of WF checking do we need for neg impls?
|
||||||
|
if trait_ref.is_some() && !is_auto {
|
||||||
|
span_err!(tcx.sess, item.span, E0192,
|
||||||
|
"negative impls are only allowed for \
|
||||||
|
auto traits (e.g., `Send` and `Sync`)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemFn(..) => {
|
hir::ItemFn(..) => {
|
||||||
|
@ -661,12 +666,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_192(tcx: TyCtxt, span: Span) {
|
|
||||||
span_err!(tcx.sess, span, E0192,
|
|
||||||
"negative impls are only allowed for traits with \
|
|
||||||
default impls (e.g., `Send` and `Sync`)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
|
fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
|
||||||
-> DiagnosticBuilder<'tcx> {
|
-> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(tcx.sess, span, E0392,
|
let mut err = struct_span_err!(tcx.sess, span, E0392,
|
||||||
|
|
|
@ -93,23 +93,11 @@ struct InherentCollect<'a, 'tcx: 'a> {
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
|
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
|
||||||
fn visit_item(&mut self, item: &hir::Item) {
|
fn visit_item(&mut self, item: &hir::Item) {
|
||||||
let (unsafety, ty) = match item.node {
|
let ty = match item.node {
|
||||||
hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
|
hir::ItemImpl(.., None, ref ty, _) => ty,
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
|
|
||||||
match unsafety {
|
|
||||||
hir::Unsafety::Normal => {
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
hir::Unsafety::Unsafe => {
|
|
||||||
span_err!(self.tcx.sess,
|
|
||||||
item.span,
|
|
||||||
E0197,
|
|
||||||
"inherent impls cannot be declared as unsafe");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
let self_ty = self.tcx.type_of(def_id);
|
let self_ty = self.tcx.type_of(def_id);
|
||||||
let lang_items = self.tcx.lang_items();
|
let lang_items = self.tcx.lang_items();
|
||||||
|
|
|
@ -67,16 +67,15 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In addition to the above rules, we restrict impls of defaulted traits
|
// In addition to the above rules, we restrict impls of auto traits
|
||||||
// so that they can only be implemented on nominal types, such as structs,
|
// so that they can only be implemented on nominal types, such as structs,
|
||||||
// enums or foreign types. To see why this restriction exists, consider the
|
// enums or foreign types. To see why this restriction exists, consider the
|
||||||
// following example (#22978). Imagine that crate A defines a defaulted trait
|
// following example (#22978). Imagine that crate A defines an auto trait
|
||||||
// `Foo` and a fn that operates on pairs of types:
|
// `Foo` and a fn that operates on pairs of types:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// // Crate A
|
// // Crate A
|
||||||
// trait Foo { }
|
// auto trait Foo { }
|
||||||
// impl Foo for .. { }
|
|
||||||
// fn two_foos<A:Foo,B:Foo>(..) {
|
// fn two_foos<A:Foo,B:Foo>(..) {
|
||||||
// one_foo::<(A,B)>(..)
|
// one_foo::<(A,B)>(..)
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -37,14 +37,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
|
||||||
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||||
let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
|
let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
|
||||||
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
|
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
|
||||||
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
|
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||||
span_err!(self.tcx.sess,
|
|
||||||
item.span,
|
|
||||||
E0198,
|
|
||||||
"negative implementations are not unsafe");
|
|
||||||
}
|
|
||||||
|
|
||||||
(Unsafety::Normal, None, Unsafety::Unsafe, _) => {
|
|
||||||
span_err!(self.tcx.sess,
|
span_err!(self.tcx.sess,
|
||||||
item.span,
|
item.span,
|
||||||
E0199,
|
E0199,
|
||||||
|
@ -69,6 +62,10 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
|
||||||
g.attr_name());
|
g.attr_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
|
||||||
|
// Reported in AST validation
|
||||||
|
self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
|
||||||
|
}
|
||||||
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
|
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
|
||||||
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||||
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||||
|
|
|
@ -1715,7 +1715,7 @@ type Foo = Trait<Bar=i32>; // ok!
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0192: r##"
|
E0192: r##"
|
||||||
Negative impls are only allowed for traits with default impls. For more
|
Negative impls are only allowed for auto traits. For more
|
||||||
information see the [opt-in builtin traits RFC][RFC 19].
|
information see the [opt-in builtin traits RFC][RFC 19].
|
||||||
|
|
||||||
[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
|
[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
|
||||||
|
@ -1821,52 +1821,6 @@ impl Trait for Foo {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0197: r##"
|
|
||||||
Inherent implementations (one that do not implement a trait but provide
|
|
||||||
methods associated with a type) are always safe because they are not
|
|
||||||
implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
|
|
||||||
implementation will resolve this error.
|
|
||||||
|
|
||||||
```compile_fail,E0197
|
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
// this will cause this error
|
|
||||||
unsafe impl Foo { }
|
|
||||||
// converting it to this will fix it
|
|
||||||
impl Foo { }
|
|
||||||
```
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0198: r##"
|
|
||||||
A negative implementation is one that excludes a type from implementing a
|
|
||||||
particular trait. Not being able to use a trait is always a safe operation,
|
|
||||||
so negative implementations are always safe and never need to be marked as
|
|
||||||
unsafe.
|
|
||||||
|
|
||||||
```compile_fail
|
|
||||||
#![feature(optin_builtin_traits)]
|
|
||||||
|
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
// unsafe is unnecessary
|
|
||||||
unsafe impl !Clone for Foo { }
|
|
||||||
```
|
|
||||||
|
|
||||||
This will compile:
|
|
||||||
|
|
||||||
```
|
|
||||||
#![feature(optin_builtin_traits)]
|
|
||||||
|
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
auto trait Enterprise {}
|
|
||||||
|
|
||||||
impl !Enterprise for Foo { }
|
|
||||||
```
|
|
||||||
|
|
||||||
Please note that negative impls are only allowed for traits with default impls.
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0199: r##"
|
E0199: r##"
|
||||||
Safe traits should not have unsafe implementations, therefore marking an
|
Safe traits should not have unsafe implementations, therefore marking an
|
||||||
implementation for a safe trait unsafe will cause a compiler error. Removing
|
implementation for a safe trait unsafe will cause a compiler error. Removing
|
||||||
|
|
|
@ -71,7 +71,7 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
|
type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
|
||||||
|
|
||||||
/// How to parse a path.
|
/// How to parse a path.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
@ -151,10 +151,9 @@ macro_rules! maybe_whole {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
|
fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
|
||||||
-> Vec<Attribute> {
|
if let Some(ref mut rhs) = rhs {
|
||||||
if let Some(ref attrs) = rhs {
|
lhs.append(rhs);
|
||||||
lhs.extend(attrs.iter().cloned())
|
|
||||||
}
|
}
|
||||||
lhs
|
lhs
|
||||||
}
|
}
|
||||||
|
@ -1347,7 +1346,7 @@ impl<'a> Parser<'a> {
|
||||||
Function Style
|
Function Style
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let unsafety = self.parse_unsafety()?;
|
let unsafety = self.parse_unsafety();
|
||||||
let abi = if self.eat_keyword(keywords::Extern) {
|
let abi = if self.eat_keyword(keywords::Extern) {
|
||||||
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1370,11 +1369,12 @@ impl<'a> Parser<'a> {
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
|
/// Parse unsafety: `unsafe` or nothing.
|
||||||
|
fn parse_unsafety(&mut self) -> Unsafety {
|
||||||
if self.eat_keyword(keywords::Unsafe) {
|
if self.eat_keyword(keywords::Unsafe) {
|
||||||
return Ok(Unsafety::Unsafe);
|
Unsafety::Unsafe
|
||||||
} else {
|
} else {
|
||||||
return Ok(Unsafety::Normal);
|
Unsafety::Normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4094,28 +4094,6 @@ impl<'a> Parser<'a> {
|
||||||
self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
|
self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_defaultness(&self) -> bool {
|
|
||||||
// `pub` is included for better error messages
|
|
||||||
self.token.is_keyword(keywords::Default) &&
|
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
|
|
||||||
t.is_keyword(keywords::Const) ||
|
|
||||||
t.is_keyword(keywords::Fn) ||
|
|
||||||
t.is_keyword(keywords::Unsafe) ||
|
|
||||||
t.is_keyword(keywords::Extern) ||
|
|
||||||
t.is_keyword(keywords::Type) ||
|
|
||||||
t.is_keyword(keywords::Pub))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eat_defaultness(&mut self) -> bool {
|
|
||||||
let is_defaultness = self.is_defaultness();
|
|
||||||
if is_defaultness {
|
|
||||||
self.bump()
|
|
||||||
} else {
|
|
||||||
self.expected_tokens.push(TokenType::Keyword(keywords::Default));
|
|
||||||
}
|
|
||||||
is_defaultness
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
|
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
|
||||||
-> PResult<'a, Option<P<Item>>> {
|
-> PResult<'a, Option<P<Item>>> {
|
||||||
let token_lo = self.span;
|
let token_lo = self.span;
|
||||||
|
@ -5126,7 +5104,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_item_fn(&mut self,
|
fn parse_item_fn(&mut self,
|
||||||
unsafety: Unsafety,
|
unsafety: Unsafety,
|
||||||
constness: Spanned<Constness>,
|
constness: Spanned<Constness>,
|
||||||
abi: abi::Abi)
|
abi: Abi)
|
||||||
-> PResult<'a, ItemInfo> {
|
-> PResult<'a, ItemInfo> {
|
||||||
let (ident, mut generics) = self.parse_fn_header()?;
|
let (ident, mut generics) = self.parse_fn_header()?;
|
||||||
let decl = self.parse_fn_decl(false)?;
|
let decl = self.parse_fn_decl(false)?;
|
||||||
|
@ -5150,13 +5128,10 @@ impl<'a> Parser<'a> {
|
||||||
/// - `const unsafe fn`
|
/// - `const unsafe fn`
|
||||||
/// - `extern fn`
|
/// - `extern fn`
|
||||||
/// - etc
|
/// - etc
|
||||||
pub fn parse_fn_front_matter(&mut self)
|
pub fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
|
||||||
-> PResult<'a, (Spanned<ast::Constness>,
|
|
||||||
ast::Unsafety,
|
|
||||||
abi::Abi)> {
|
|
||||||
let is_const_fn = self.eat_keyword(keywords::Const);
|
let is_const_fn = self.eat_keyword(keywords::Const);
|
||||||
let const_span = self.prev_span;
|
let const_span = self.prev_span;
|
||||||
let unsafety = self.parse_unsafety()?;
|
let unsafety = self.parse_unsafety();
|
||||||
let (constness, unsafety, abi) = if is_const_fn {
|
let (constness, unsafety, abi) = if is_const_fn {
|
||||||
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5191,7 +5166,7 @@ impl<'a> Parser<'a> {
|
||||||
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
|
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
|
||||||
let lo = self.span;
|
let lo = self.span;
|
||||||
let vis = self.parse_visibility(false)?;
|
let vis = self.parse_visibility(false)?;
|
||||||
let defaultness = self.parse_defaultness()?;
|
let defaultness = self.parse_defaultness();
|
||||||
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
||||||
// This parses the grammar:
|
// This parses the grammar:
|
||||||
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
|
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
|
||||||
|
@ -5284,7 +5259,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse a method or a macro invocation in a trait impl.
|
/// Parse a method or a macro invocation in a trait impl.
|
||||||
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
|
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
|
||||||
-> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics,
|
-> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
|
||||||
ast::ImplItemKind)> {
|
ast::ImplItemKind)> {
|
||||||
// code copied from parse_macro_use_or_failure... abstraction!
|
// code copied from parse_macro_use_or_failure... abstraction!
|
||||||
if self.token.is_path_start() && !self.is_extern_non_path() {
|
if self.token.is_path_start() && !self.is_extern_non_path() {
|
||||||
|
@ -5373,83 +5348,97 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses items implementations variants
|
fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
|
||||||
/// impl<T> Foo { ... }
|
|
||||||
/// impl<T> ToString for &'static T { ... }
|
|
||||||
fn parse_item_impl(&mut self,
|
|
||||||
unsafety: ast::Unsafety,
|
|
||||||
defaultness: Defaultness) -> PResult<'a, ItemInfo> {
|
|
||||||
|
|
||||||
// First, parse type parameters if necessary.
|
|
||||||
let mut generics = self.parse_generics()?;
|
|
||||||
|
|
||||||
// Special case: if the next identifier that follows is '(', don't
|
|
||||||
// allow this to be parsed as a trait.
|
|
||||||
let could_be_trait = self.token != token::OpenDelim(token::Paren);
|
|
||||||
|
|
||||||
let neg_span = self.span;
|
|
||||||
let polarity = if self.eat(&token::Not) {
|
|
||||||
ast::ImplPolarity::Negative
|
|
||||||
} else {
|
|
||||||
ast::ImplPolarity::Positive
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the trait.
|
|
||||||
let mut ty = self.parse_ty()?;
|
|
||||||
|
|
||||||
// Parse traits, if necessary.
|
|
||||||
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
|
|
||||||
// New-style trait. Reinterpret the type as a trait.
|
|
||||||
match ty.node {
|
|
||||||
TyKind::Path(None, ref path) => {
|
|
||||||
Some(TraitRef {
|
|
||||||
path: (*path).clone(),
|
|
||||||
ref_id: ty.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.span_err(ty.span, "not a trait");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if polarity == ast::ImplPolarity::Negative {
|
|
||||||
// This is a negated type implementation
|
|
||||||
// `impl !MyType {}`, which is not allowed.
|
|
||||||
self.span_err(neg_span, "inherent implementation can't be negated");
|
|
||||||
}
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if opt_trait.is_some() {
|
|
||||||
ty = if self.eat(&token::DotDot) {
|
|
||||||
P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID })
|
|
||||||
} else {
|
|
||||||
self.parse_ty()?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
|
||||||
|
|
||||||
self.expect(&token::OpenDelim(token::Brace))?;
|
self.expect(&token::OpenDelim(token::Brace))?;
|
||||||
let attrs = self.parse_inner_attributes()?;
|
let attrs = self.parse_inner_attributes()?;
|
||||||
|
|
||||||
let mut impl_items = vec![];
|
let mut impl_items = Vec::new();
|
||||||
while !self.eat(&token::CloseDelim(token::Brace)) {
|
while !self.eat(&token::CloseDelim(token::Brace)) {
|
||||||
let mut at_end = false;
|
let mut at_end = false;
|
||||||
match self.parse_impl_item(&mut at_end) {
|
match self.parse_impl_item(&mut at_end) {
|
||||||
Ok(item) => impl_items.push(item),
|
Ok(impl_item) => impl_items.push(impl_item),
|
||||||
Err(mut e) => {
|
Err(mut err) => {
|
||||||
e.emit();
|
err.emit();
|
||||||
if !at_end {
|
if !at_end {
|
||||||
self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
|
self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok((impl_items, attrs))
|
||||||
|
}
|
||||||
|
|
||||||
Ok((keywords::Invalid.ident(),
|
/// Parses an implementation item, `impl` keyword is already parsed.
|
||||||
ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
|
/// impl<'a, T> TYPE { /* impl items */ }
|
||||||
Some(attrs)))
|
/// impl<'a, T> TRAIT for TYPE { /* impl items */ }
|
||||||
|
/// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
|
||||||
|
/// We actually parse slightly more relaxed grammar for better error reporting and recovery.
|
||||||
|
/// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
|
||||||
|
/// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
|
||||||
|
fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
|
||||||
|
-> PResult<'a, ItemInfo> {
|
||||||
|
// First, parse generic parameters if necessary.
|
||||||
|
// FIXME: Disambiguate generic parameters and qualified paths (`impl <A as B>::C {}`).
|
||||||
|
let mut generics = self.parse_generics()?;
|
||||||
|
|
||||||
|
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
|
||||||
|
let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
|
||||||
|
self.bump(); // `!`
|
||||||
|
ast::ImplPolarity::Negative
|
||||||
|
} else {
|
||||||
|
ast::ImplPolarity::Positive
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse both types and traits as a type, then reinterpret if necessary.
|
||||||
|
let ty_first = self.parse_ty()?;
|
||||||
|
|
||||||
|
// If `for` is missing we try to recover.
|
||||||
|
let has_for = self.eat_keyword(keywords::For);
|
||||||
|
let missing_for_span = self.prev_span.between(self.span);
|
||||||
|
|
||||||
|
let ty_second = if self.token == token::DotDot {
|
||||||
|
// We need to report this error after `cfg` expansion for compatibility reasons
|
||||||
|
self.bump(); // `..`, do not add it to expected tokens
|
||||||
|
Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
|
||||||
|
} else if has_for || self.token.can_begin_type() {
|
||||||
|
Some(self.parse_ty()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
|
|
||||||
|
let (impl_items, attrs) = self.parse_impl_body()?;
|
||||||
|
|
||||||
|
let item_kind = match ty_second {
|
||||||
|
Some(ty_second) => {
|
||||||
|
// impl Trait for Type
|
||||||
|
if !has_for {
|
||||||
|
self.span_err(missing_for_span, "missing `for` in a trait impl");
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty_first = ty_first.into_inner();
|
||||||
|
let path = match ty_first.node {
|
||||||
|
// This notably includes paths passed through `ty` macro fragments (#46438).
|
||||||
|
TyKind::Path(None, path) => path,
|
||||||
|
_ => {
|
||||||
|
self.span_err(ty_first.span, "expected a trait, found type");
|
||||||
|
ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let trait_ref = TraitRef { path, ref_id: ty_first.id };
|
||||||
|
|
||||||
|
ItemKind::Impl(unsafety, polarity, defaultness,
|
||||||
|
generics, Some(trait_ref), ty_second, impl_items)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// impl Type
|
||||||
|
ItemKind::Impl(unsafety, polarity, defaultness,
|
||||||
|
generics, None, ty_first, impl_items)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
|
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
|
||||||
|
@ -5722,12 +5711,21 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Visibility::Public)
|
Ok(Visibility::Public)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse defaultness: DEFAULT or nothing
|
/// Parse defaultness: `default` or nothing.
|
||||||
fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
|
fn parse_defaultness(&mut self) -> Defaultness {
|
||||||
if self.eat_defaultness() {
|
// `pub` is included for better error messages
|
||||||
Ok(Defaultness::Default)
|
if self.check_keyword(keywords::Default) &&
|
||||||
|
self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
|
||||||
|
t.is_keyword(keywords::Const) ||
|
||||||
|
t.is_keyword(keywords::Fn) ||
|
||||||
|
t.is_keyword(keywords::Unsafe) ||
|
||||||
|
t.is_keyword(keywords::Extern) ||
|
||||||
|
t.is_keyword(keywords::Type) ||
|
||||||
|
t.is_keyword(keywords::Pub)) {
|
||||||
|
self.bump(); // `default`
|
||||||
|
Defaultness::Default
|
||||||
} else {
|
} else {
|
||||||
Ok(Defaultness::Final)
|
Defaultness::Final
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5797,7 +5795,7 @@ impl<'a> Parser<'a> {
|
||||||
let (module, mut attrs) =
|
let (module, mut attrs) =
|
||||||
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
|
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
|
||||||
if warn {
|
if warn {
|
||||||
let attr = ast::Attribute {
|
let attr = Attribute {
|
||||||
id: attr::mk_attr_id(),
|
id: attr::mk_attr_id(),
|
||||||
style: ast::AttrStyle::Outer,
|
style: ast::AttrStyle::Outer,
|
||||||
path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
|
path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
|
||||||
|
@ -5837,7 +5835,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
|
pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
|
||||||
attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
|
attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5906,7 +5904,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
fn submod_path(&mut self,
|
fn submod_path(&mut self,
|
||||||
id: ast::Ident,
|
id: ast::Ident,
|
||||||
outer_attrs: &[ast::Attribute],
|
outer_attrs: &[Attribute],
|
||||||
id_sp: Span)
|
id_sp: Span)
|
||||||
-> PResult<'a, ModulePathSuccess> {
|
-> PResult<'a, ModulePathSuccess> {
|
||||||
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
|
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
|
||||||
|
@ -5999,7 +5997,7 @@ impl<'a> Parser<'a> {
|
||||||
directory_ownership: DirectoryOwnership,
|
directory_ownership: DirectoryOwnership,
|
||||||
name: String,
|
name: String,
|
||||||
id_sp: Span)
|
id_sp: Span)
|
||||||
-> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
|
-> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
|
||||||
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
|
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
|
||||||
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
|
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
|
||||||
let mut err = String::from("circular modules: ");
|
let mut err = String::from("circular modules: ");
|
||||||
|
@ -6122,7 +6120,7 @@ impl<'a> Parser<'a> {
|
||||||
/// extern {}
|
/// extern {}
|
||||||
fn parse_item_foreign_mod(&mut self,
|
fn parse_item_foreign_mod(&mut self,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
opt_abi: Option<abi::Abi>,
|
opt_abi: Option<Abi>,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
mut attrs: Vec<Attribute>)
|
mut attrs: Vec<Attribute>)
|
||||||
-> PResult<'a, P<Item>> {
|
-> PResult<'a, P<Item>> {
|
||||||
|
@ -6225,7 +6223,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses a string as an ABI spec on an extern type or module. Consumes
|
/// Parses a string as an ABI spec on an extern type or module. Consumes
|
||||||
/// the `extern` keyword, if one is found.
|
/// the `extern` keyword, if one is found.
|
||||||
fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
|
fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
|
||||||
match self.token {
|
match self.token {
|
||||||
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
|
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
|
||||||
let sp = self.span;
|
let sp = self.span;
|
||||||
|
@ -6330,11 +6328,7 @@ impl<'a> Parser<'a> {
|
||||||
|| (self.check_keyword(keywords::Unsafe)
|
|| (self.check_keyword(keywords::Unsafe)
|
||||||
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
|
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
|
||||||
// CONST FUNCTION ITEM
|
// CONST FUNCTION ITEM
|
||||||
let unsafety = if self.eat_keyword(keywords::Unsafe) {
|
let unsafety = self.parse_unsafety();
|
||||||
Unsafety::Unsafe
|
|
||||||
} else {
|
|
||||||
Unsafety::Normal
|
|
||||||
};
|
|
||||||
self.bump();
|
self.bump();
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(unsafety,
|
self.parse_item_fn(unsafety,
|
||||||
|
@ -6370,7 +6364,7 @@ impl<'a> Parser<'a> {
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
|
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
|
||||||
{
|
{
|
||||||
// UNSAFE TRAIT ITEM
|
// UNSAFE TRAIT ITEM
|
||||||
self.expect_keyword(keywords::Unsafe)?;
|
self.bump(); // `unsafe`
|
||||||
let is_auto = if self.eat_keyword(keywords::Trait) {
|
let is_auto = if self.eat_keyword(keywords::Trait) {
|
||||||
IsAuto::No
|
IsAuto::No
|
||||||
} else {
|
} else {
|
||||||
|
@ -6379,7 +6373,7 @@ impl<'a> Parser<'a> {
|
||||||
IsAuto::Yes
|
IsAuto::Yes
|
||||||
};
|
};
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
|
self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
let item = self.mk_item(lo.to(prev_span),
|
||||||
ident,
|
ident,
|
||||||
|
@ -6388,26 +6382,21 @@ impl<'a> Parser<'a> {
|
||||||
maybe_append(attrs, extra_attrs));
|
maybe_append(attrs, extra_attrs));
|
||||||
return Ok(Some(item));
|
return Ok(Some(item));
|
||||||
}
|
}
|
||||||
if (self.check_keyword(keywords::Unsafe) &&
|
if self.check_keyword(keywords::Impl) ||
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
|
self.check_keyword(keywords::Unsafe) &&
|
||||||
(self.check_keyword(keywords::Default) &&
|
self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
|
self.check_keyword(keywords::Default) &&
|
||||||
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
|
self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
|
||||||
{
|
self.check_keyword(keywords::Default) &&
|
||||||
|
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
|
||||||
// IMPL ITEM
|
// IMPL ITEM
|
||||||
let defaultness = self.parse_defaultness()?;
|
let defaultness = self.parse_defaultness();
|
||||||
self.expect_keyword(keywords::Unsafe)?;
|
let unsafety = self.parse_unsafety();
|
||||||
self.expect_keyword(keywords::Impl)?;
|
self.expect_keyword(keywords::Impl)?;
|
||||||
let (ident,
|
let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
|
||||||
item_,
|
let span = lo.to(self.prev_span);
|
||||||
extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
|
return Ok(Some(self.mk_item(span, ident, item, visibility,
|
||||||
let prev_span = self.prev_span;
|
maybe_append(attrs, extra_attrs))));
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
|
||||||
ident,
|
|
||||||
item_,
|
|
||||||
visibility,
|
|
||||||
maybe_append(attrs, extra_attrs));
|
|
||||||
return Ok(Some(item));
|
|
||||||
}
|
}
|
||||||
if self.check_keyword(keywords::Fn) {
|
if self.check_keyword(keywords::Fn) {
|
||||||
// FUNCTION ITEM
|
// FUNCTION ITEM
|
||||||
|
@ -6428,7 +6417,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.check_keyword(keywords::Unsafe)
|
if self.check_keyword(keywords::Unsafe)
|
||||||
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
||||||
// UNSAFE FUNCTION ITEM
|
// UNSAFE FUNCTION ITEM
|
||||||
self.bump();
|
self.bump(); // `unsafe`
|
||||||
let abi = if self.eat_keyword(keywords::Extern) {
|
let abi = if self.eat_keyword(keywords::Extern) {
|
||||||
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
||||||
} else {
|
} else {
|
||||||
|
@ -6495,25 +6484,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
// TRAIT ITEM
|
// TRAIT ITEM
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
|
self.parse_item_trait(is_auto, Unsafety::Normal)?;
|
||||||
let prev_span = self.prev_span;
|
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
|
||||||
ident,
|
|
||||||
item_,
|
|
||||||
visibility,
|
|
||||||
maybe_append(attrs, extra_attrs));
|
|
||||||
return Ok(Some(item));
|
|
||||||
}
|
|
||||||
if (self.check_keyword(keywords::Impl)) ||
|
|
||||||
(self.check_keyword(keywords::Default) &&
|
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
|
|
||||||
{
|
|
||||||
// IMPL ITEM
|
|
||||||
let defaultness = self.parse_defaultness()?;
|
|
||||||
self.expect_keyword(keywords::Impl)?;
|
|
||||||
let (ident,
|
|
||||||
item_,
|
|
||||||
extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
|
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
let item = self.mk_item(lo.to(prev_span),
|
||||||
ident,
|
ident,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
unsafe impl !Clone for Foo { } //~ ERROR negative implementations are not unsafe [E0198]
|
unsafe impl !Send for Foo { } //~ ERROR E0198
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ use std::marker::Send;
|
||||||
struct TestType;
|
struct TestType;
|
||||||
|
|
||||||
unsafe impl !Send for TestType {}
|
unsafe impl !Send for TestType {}
|
||||||
//~^ ERROR negative implementations are not unsafe
|
//~^ ERROR negative impls cannot be unsafe
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
23
src/test/compile-fail/issue-46438.rs
Normal file
23
src/test/compile-fail/issue-46438.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
macro_rules! m {
|
||||||
|
($my_type: ty) => {
|
||||||
|
impl $my_type for u8 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait {}
|
||||||
|
|
||||||
|
m!(Tr);
|
||||||
|
|
||||||
|
m!(&'static u8); //~ ERROR expected a trait, found type
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -9,8 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
|
// Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
|
||||||
// the `PhantomData<T>` type itself (which almost always implements a "default" trait
|
// the `PhantomData<T>` type itself (which almost always implements an auto trait)
|
||||||
// (`impl Trait for ..`))
|
|
||||||
|
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
#![feature(specialization)]
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
struct Z;
|
||||||
|
|
||||||
|
default impl S {} //~ ERROR inherent impls cannot be default
|
||||||
|
|
||||||
|
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
|
||||||
|
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
|
||||||
|
|
||||||
|
trait Tr {}
|
||||||
|
default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
|
|
@ -14,7 +14,7 @@ struct TestType;
|
||||||
|
|
||||||
trait TestTrait {}
|
trait TestTrait {}
|
||||||
|
|
||||||
unsafe impl !Send for TestType {}
|
impl !Send for TestType {}
|
||||||
//~^ ERROR negative trait bounds
|
//~^ ERROR negative trait bounds
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
|
||||||
|
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
use std::marker::Send;
|
use std::marker::Send;
|
||||||
|
@ -17,19 +15,23 @@ use std::marker::Send;
|
||||||
struct TestType;
|
struct TestType;
|
||||||
|
|
||||||
impl !TestType {}
|
impl !TestType {}
|
||||||
//~^ ERROR inherent implementation can't be negated
|
//~^ ERROR inherent impls cannot be negative
|
||||||
|
|
||||||
trait TestTrait {}
|
trait TestTrait {}
|
||||||
|
|
||||||
unsafe impl !Send for TestType {}
|
unsafe impl !Send for TestType {}
|
||||||
|
//~^ ERROR negative impls cannot be unsafe
|
||||||
impl !TestTrait for TestType {}
|
impl !TestTrait for TestType {}
|
||||||
|
//~^ ERROR negative impls are only allowed for auto traits
|
||||||
|
|
||||||
struct TestType2<T>;
|
struct TestType2<T>(T);
|
||||||
|
|
||||||
impl<T> !TestType2<T> {}
|
impl<T> !TestType2<T> {}
|
||||||
//~^ ERROR inherent implementation can't be negated
|
//~^ ERROR inherent impls cannot be negative
|
||||||
|
|
||||||
unsafe impl<T> !Send for TestType2<T> {}
|
unsafe impl<T> !Send for TestType2<T> {}
|
||||||
|
//~^ ERROR negative impls cannot be unsafe
|
||||||
impl<T> !TestTrait for TestType2<T> {}
|
impl<T> !TestTrait for TestType2<T> {}
|
||||||
|
//~^ ERROR negative impls are only allowed for auto traits
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
struct SomeStruct;
|
struct SomeStruct;
|
||||||
|
|
||||||
unsafe impl SomeStruct { //~ ERROR inherent impls cannot be declared as unsafe
|
unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
|
||||||
fn foo(self) { }
|
fn foo(self) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,6 @@ trait TestTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl !TestTrait for TestType {}
|
impl !TestTrait for TestType {}
|
||||||
//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
|
//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -15,9 +15,7 @@ trait Foo {
|
||||||
|
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl Foo + Owned for Bar {
|
impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
|
||||||
//~^ ERROR not a trait
|
|
||||||
//~^^ ERROR expected one of `where` or `{`, found `Bar`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub trait Paramters { type SelfRef; }
|
pub trait Parameters { type SelfRef; }
|
||||||
|
|
||||||
struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
|
struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
|
||||||
struct BP;
|
struct BP;
|
||||||
|
|
||||||
impl<'a> Paramters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
|
impl<'a> Parameters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
|
||||||
impl Paramters for BP { type SelfRef = Box<X<BP>>; }
|
impl Parameters for BP { type SelfRef = Box<X<BP>>; }
|
||||||
|
|
||||||
pub struct Y;
|
pub struct Y;
|
||||||
pub enum X<P: Paramters> {
|
pub enum X<P: Parameters> {
|
||||||
Nothing,
|
Nothing,
|
||||||
SameAgain(P::SelfRef, Y)
|
SameAgain(P::SelfRef, Y)
|
||||||
}
|
}
|
||||||
|
|
21
src/test/ui/span/impl-parsing.rs
Normal file
21
src/test/ui/span/impl-parsing.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||||
|
|
||||||
|
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 `impl`, found `FAIL`
|
32
src/test/ui/span/impl-parsing.stderr
Normal file
32
src/test/ui/span/impl-parsing.stderr
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
error: missing `for` in a trait impl
|
||||||
|
--> $DIR/impl-parsing.rs:16:11
|
||||||
|
|
|
||||||
|
16 | impl Trait Type {} //~ ERROR missing `for` in a trait impl
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: missing `for` in a trait impl
|
||||||
|
--> $DIR/impl-parsing.rs:17:11
|
||||||
|
|
|
||||||
|
17 | impl Trait .. {} //~ ERROR missing `for` in a trait impl
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: expected a trait, found type
|
||||||
|
--> $DIR/impl-parsing.rs:18:6
|
||||||
|
|
|
||||||
|
18 | impl ?Sized for Type {} //~ ERROR expected a trait, found type
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: expected a trait, found type
|
||||||
|
--> $DIR/impl-parsing.rs:19:6
|
||||||
|
|
|
||||||
|
19 | impl ?Sized for .. {} //~ ERROR expected a trait, found type
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: expected `impl`, found `FAIL`
|
||||||
|
--> $DIR/impl-parsing.rs:21:16
|
||||||
|
|
|
||||||
|
21 | default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
|
||||||
|
| ^^^^ expected `impl` here
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
error[E0318]: cannot create default implementations for traits outside the crate they're defined in; define a new trait instead
|
|
||||||
--> $DIR/typeck-default-trait-impl-outside-crate.rs:14:6
|
|
||||||
|
|
|
||||||
14 | impl Copy for .. {} //~ ERROR E0318
|
|
||||||
| ^^^^ `Copy` trait not defined in this crate
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue