mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-12 07:43:31 +00:00
refactor and centralize on_unimplemented
parsing
This commit is contained in:
parent
fc54bf949d
commit
243aa12d6e
@ -688,8 +688,8 @@ See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
|
||||
"##,
|
||||
|
||||
E0214: r##"
|
||||
A generic type was described using parentheses rather than angle brackets. For
|
||||
example:
|
||||
A generic type was described using parentheses rather than angle brackets.
|
||||
For example:
|
||||
|
||||
```compile_fail,E0214
|
||||
fn main() {
|
||||
@ -702,6 +702,93 @@ Parentheses are currently only used with generic types when defining parameters
|
||||
for `Fn`-family traits.
|
||||
"##,
|
||||
|
||||
E0230: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
There will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces contain an identifier which doesn't
|
||||
match with any of the type parameters or the string `Self`. This might happen
|
||||
if you misspelled a type parameter, or if you intended to use literal curly
|
||||
braces. If it is the latter, escape the curly braces with a second curly brace
|
||||
of the same type; e.g. a literal `{` is `{{`.
|
||||
"##,
|
||||
|
||||
E0231: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
there will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces do not contain an identifier. Please
|
||||
add one of the same name as a type parameter. If you intended to use literal
|
||||
braces, use `{{` and `}}` to escape them.
|
||||
"##,
|
||||
|
||||
E0232: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
there will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
For this to work, some note must be specified. An empty attribute will not do
|
||||
anything, please remove the attribute or add some helpful note for users of the
|
||||
trait.
|
||||
"##,
|
||||
|
||||
E0261: r##"
|
||||
When using a lifetime like `'a` in a type, it must be declared before being
|
||||
used.
|
||||
@ -917,92 +1004,6 @@ for v in &vs {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0272: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
There will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces contain an identifier which doesn't
|
||||
match with any of the type parameters or the string `Self`. This might happen
|
||||
if you misspelled a type parameter, or if you intended to use literal curly
|
||||
braces. If it is the latter, escape the curly braces with a second curly brace
|
||||
of the same type; e.g. a literal `{` is `{{`.
|
||||
"##,
|
||||
|
||||
E0273: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
there will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces do not contain an identifier. Please
|
||||
add one of the same name as a type parameter. If you intended to use literal
|
||||
braces, use `{{` and `}}` to escape them.
|
||||
"##,
|
||||
|
||||
E0274: r##"
|
||||
The `#[rustc_on_unimplemented]` attribute lets you specify a custom error
|
||||
message for when a particular trait isn't implemented on a type placed in a
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
trait Index<Idx> { /* ... */ }
|
||||
|
||||
foo(true); // `bool` does not implement `Index<u8>`
|
||||
```
|
||||
|
||||
there will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
For this to work, some note must be specified. An empty attribute will not do
|
||||
anything, please remove the attribute or add some helpful note for users of the
|
||||
trait.
|
||||
"##,
|
||||
|
||||
E0275: r##"
|
||||
This error occurs when there was a recursive trait requirement that overflowed
|
||||
@ -2011,6 +2012,9 @@ register_diagnostics! {
|
||||
// E0102, // replaced with E0282
|
||||
// E0134,
|
||||
// E0135,
|
||||
// E0271, // on_unimplemented #0
|
||||
// E0272, // on_unimplemented #1
|
||||
// E0273, // on_unimplemented #2
|
||||
E0278, // requirement is not satisfied
|
||||
E0279, // requirement is not satisfied
|
||||
E0280, // requirement is not satisfied
|
||||
|
@ -39,9 +39,148 @@ use ty::fast_reject;
|
||||
use ty::fold::TypeFolder;
|
||||
use ty::subst::Subst;
|
||||
use ty::SubtypePredicate;
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use syntax_pos::symbol::InternedString;
|
||||
|
||||
pub struct OnUnimplementedFormatString(InternedString);
|
||||
pub struct OnUnimplementedInfo {
|
||||
note: OnUnimplementedFormatString
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> OnUnimplementedInfo {
|
||||
pub fn of_item(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_def_id: DefId,
|
||||
impl_def_id: DefId,
|
||||
span: Span)
|
||||
-> Result<Option<Self>, ErrorReported>
|
||||
{
|
||||
let attrs = tcx.get_attrs(impl_def_id);
|
||||
|
||||
let attr = if let Some(item) =
|
||||
attrs.into_iter().find(|a| a.check_name("rustc_on_unimplemented"))
|
||||
{
|
||||
item
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let span = attr.span.substitute_dummy(span);
|
||||
if let Some(label) = attr.value_str() {
|
||||
Ok(Some(OnUnimplementedInfo {
|
||||
note: OnUnimplementedFormatString::try_parse(
|
||||
tcx, trait_def_id, label.as_str(), span)?
|
||||
}))
|
||||
} else {
|
||||
struct_span_err!(
|
||||
tcx.sess, span, E0232,
|
||||
"this attribute must have a value")
|
||||
.span_label(attr.span, "attribute requires a value")
|
||||
.note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`"))
|
||||
.emit();
|
||||
Err(ErrorReported)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||
pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_def_id: DefId,
|
||||
from: InternedString,
|
||||
err_sp: Span)
|
||||
-> Result<Self, ErrorReported>
|
||||
{
|
||||
let result = OnUnimplementedFormatString(from);
|
||||
result.verify(tcx, trait_def_id, err_sp)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn verify(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_def_id: DefId,
|
||||
span: Span)
|
||||
-> Result<(), ErrorReported>
|
||||
{
|
||||
let name = tcx.item_name(trait_def_id).as_str();
|
||||
let generics = tcx.generics_of(trait_def_id);
|
||||
let parser = Parser::new(&self.0);
|
||||
let types = &generics.types;
|
||||
let mut result = Ok(());
|
||||
for token in parser {
|
||||
match token {
|
||||
Piece::String(_) => (), // Normal string, no need to check it
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
// `{Self}` is allowed
|
||||
Position::ArgumentNamed(s) if s == "Self" => (),
|
||||
// `{ThisTraitsName}` is allowed
|
||||
Position::ArgumentNamed(s) if s == name => (),
|
||||
// So is `{A}` if A is a type parameter
|
||||
Position::ArgumentNamed(s) => match types.iter().find(|t| {
|
||||
t.name == s
|
||||
}) {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
span_err!(tcx.sess, span, E0230,
|
||||
"there is no type parameter \
|
||||
{} on trait {}",
|
||||
s, name);
|
||||
result = Err(ErrorReported);
|
||||
}
|
||||
},
|
||||
// `{:1}` and `{}` are not to be used
|
||||
Position::ArgumentIs(_) => {
|
||||
span_err!(tcx.sess, span, E0231,
|
||||
"only named substitution \
|
||||
parameters are allowed");
|
||||
result = Err(ErrorReported);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn format(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>)
|
||||
-> String
|
||||
{
|
||||
let name = tcx.item_name(trait_ref.def_id).as_str();
|
||||
let trait_str = tcx.item_path_str(trait_ref.def_id);
|
||||
let generics = tcx.generics_of(trait_ref.def_id);
|
||||
let generic_map = generics.types.iter().map(|param| {
|
||||
(param.name.as_str().to_string(),
|
||||
trait_ref.substs.type_for_def(param).to_string())
|
||||
}).collect::<FxHashMap<String, String>>();
|
||||
|
||||
let parser = Parser::new(&self.0);
|
||||
parser.map(|p| {
|
||||
match p {
|
||||
Piece::String(s) => s,
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
Position::ArgumentNamed(s) => match generic_map.get(s) {
|
||||
Some(val) => val,
|
||||
None if s == name => {
|
||||
&trait_str
|
||||
}
|
||||
None => {
|
||||
bug!("broken on_unimplemented {:?} for {:?}: \
|
||||
no argument matching {:?}",
|
||||
self.0, trait_ref, s)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
bug!("broken on_unimplemented {:?} - bad \
|
||||
format arg", self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn report_fulfillment_errors(&self,
|
||||
@ -323,70 +462,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
.unwrap_or(trait_ref.def_id());
|
||||
let trait_ref = trait_ref.skip_binder();
|
||||
|
||||
let span = obligation.cause.span;
|
||||
let mut report = None;
|
||||
if let Some(item) = self.tcx
|
||||
.get_attrs(def_id)
|
||||
.into_iter()
|
||||
.filter(|a| a.check_name("rustc_on_unimplemented"))
|
||||
.next()
|
||||
{
|
||||
let name = self.tcx.item_name(def_id).as_str();
|
||||
let err_sp = item.span.substitute_dummy(span);
|
||||
let trait_str = self.tcx.item_path_str(trait_ref.def_id);
|
||||
if let Some(istring) = item.value_str() {
|
||||
let istring = &*istring.as_str();
|
||||
let generics = self.tcx.generics_of(trait_ref.def_id);
|
||||
let generic_map = generics.types.iter().map(|param| {
|
||||
(param.name.as_str().to_string(),
|
||||
trait_ref.substs.type_for_def(param).to_string())
|
||||
}).collect::<FxHashMap<String, String>>();
|
||||
let parser = Parser::new(istring);
|
||||
let mut errored = false;
|
||||
let err: String = parser.filter_map(|p| {
|
||||
match p {
|
||||
Piece::String(s) => Some(s),
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
Position::ArgumentNamed(s) => match generic_map.get(s) {
|
||||
Some(val) => Some(val),
|
||||
None if s == name => {
|
||||
Some(&trait_str)
|
||||
}
|
||||
None => {
|
||||
span_err!(self.tcx.sess, err_sp, E0272,
|
||||
"the #[rustc_on_unimplemented] attribute on trait \
|
||||
definition for {} refers to non-existent type \
|
||||
parameter {}",
|
||||
trait_str, s);
|
||||
errored = true;
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
span_err!(self.tcx.sess, err_sp, E0273,
|
||||
"the #[rustc_on_unimplemented] attribute on trait \
|
||||
definition for {} must have named format arguments, eg \
|
||||
`#[rustc_on_unimplemented = \"foo {{T}}\"]`",
|
||||
trait_str);
|
||||
errored = true;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
// Report only if the format string checks out
|
||||
if !errored {
|
||||
report = Some(err);
|
||||
}
|
||||
} else {
|
||||
span_err!(self.tcx.sess, err_sp, E0274,
|
||||
"the #[rustc_on_unimplemented] attribute on \
|
||||
trait definition for {} must have a value, \
|
||||
eg `#[rustc_on_unimplemented = \"foo\"]`",
|
||||
trait_str);
|
||||
}
|
||||
match OnUnimplementedInfo::of_item(
|
||||
self.tcx, trait_ref.def_id, def_id, obligation.cause.span
|
||||
) {
|
||||
Ok(Some(info)) => Some(info.note.format(self.tcx, *trait_ref)),
|
||||
_ => None
|
||||
}
|
||||
report
|
||||
}
|
||||
|
||||
fn find_similar_impl_candidates(&self,
|
||||
|
@ -31,6 +31,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
||||
pub use self::coherence::orphan_check;
|
||||
pub use self::coherence::overlapping_impls;
|
||||
pub use self::coherence::OrphanCheckErr;
|
||||
pub use self::error_reporting::OnUnimplementedInfo;
|
||||
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
||||
pub use self::project::MismatchedProjectionTypes;
|
||||
pub use self::project::{normalize, normalize_projection_type, Normalized};
|
||||
|
@ -85,7 +85,6 @@ use self::method::MethodCallee;
|
||||
use self::TupleArgumentsFlag::*;
|
||||
|
||||
use astconv::AstConv;
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use hir::def::{Def, CtorKind};
|
||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_back::slice::ref_slice;
|
||||
@ -1215,55 +1214,12 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
|
||||
}
|
||||
|
||||
fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
trait_def_id: DefId,
|
||||
item: &hir::Item) {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
if let Some(ref attr) = item.attrs.iter().find(|a| {
|
||||
a.check_name("rustc_on_unimplemented")
|
||||
}) {
|
||||
if let Some(istring) = attr.value_str() {
|
||||
let istring = istring.as_str();
|
||||
let name = tcx.item_name(def_id).as_str();
|
||||
let parser = Parser::new(&istring);
|
||||
let types = &generics.types;
|
||||
for token in parser {
|
||||
match token {
|
||||
Piece::String(_) => (), // Normal string, no need to check it
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
// `{Self}` is allowed
|
||||
Position::ArgumentNamed(s) if s == "Self" => (),
|
||||
// `{ThisTraitsName}` is allowed
|
||||
Position::ArgumentNamed(s) if s == name => (),
|
||||
// So is `{A}` if A is a type parameter
|
||||
Position::ArgumentNamed(s) => match types.iter().find(|t| {
|
||||
t.name == s
|
||||
}) {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
span_err!(tcx.sess, attr.span, E0230,
|
||||
"there is no type parameter \
|
||||
{} on trait {}",
|
||||
s, name);
|
||||
}
|
||||
},
|
||||
// `{:1}` and `{}` are not to be used
|
||||
Position::ArgumentIs(_) => {
|
||||
span_err!(tcx.sess, attr.span, E0231,
|
||||
"only named substitution \
|
||||
parameters are allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
struct_span_err!(
|
||||
tcx.sess, attr.span, E0232,
|
||||
"this attribute must have a value")
|
||||
.span_label(attr.span, "attribute requires a value")
|
||||
.note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`"))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
let item_def_id = tcx.hir.local_def_id(item.id);
|
||||
// an error would be reported if this fails.
|
||||
let _ = traits::OnUnimplementedInfo::of_item(
|
||||
tcx, trait_def_id, item_def_id, item.span);
|
||||
}
|
||||
|
||||
fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -2505,50 +2505,6 @@ fn baz<I>(x: &<I as Foo>::A) where I: Foo<A=Bar> {}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0230: r##"
|
||||
The trait has more type parameters specified than appear in its definition.
|
||||
|
||||
Erroneous example code:
|
||||
|
||||
```compile_fail,E0230
|
||||
#![feature(on_unimplemented)]
|
||||
#[rustc_on_unimplemented = "Trait error on `{Self}` with `<{A},{B},{C}>`"]
|
||||
// error: there is no type parameter C on trait TraitWithThreeParams
|
||||
trait TraitWithThreeParams<A,B>
|
||||
{}
|
||||
```
|
||||
|
||||
Include the correct number of type parameters and the compilation should
|
||||
proceed:
|
||||
|
||||
```
|
||||
#![feature(on_unimplemented)]
|
||||
#[rustc_on_unimplemented = "Trait error on `{Self}` with `<{A},{B},{C}>`"]
|
||||
trait TraitWithThreeParams<A,B,C> // ok!
|
||||
{}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0232: r##"
|
||||
The attribute must have a value. Erroneous code example:
|
||||
|
||||
```compile_fail,E0232
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
#[rustc_on_unimplemented] // error: this attribute must have a value
|
||||
trait Bar {}
|
||||
```
|
||||
|
||||
Please supply the missing value of the attribute. Example:
|
||||
|
||||
```
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
#[rustc_on_unimplemented = "foo"] // ok!
|
||||
trait Bar {}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0243: r##"
|
||||
This error indicates that not enough type parameters were found in a type or
|
||||
trait.
|
||||
@ -4690,7 +4646,6 @@ register_diagnostics! {
|
||||
E0224, // at least one non-builtin train is required for an object type
|
||||
E0227, // ambiguous lifetime bound, explicit lifetime bound required
|
||||
E0228, // explicit lifetime bound required
|
||||
E0231, // only named substitution parameters are allowed
|
||||
// E0233,
|
||||
// E0234,
|
||||
// E0235, // structure constructor specifies a structure of type but
|
||||
|
@ -84,7 +84,6 @@ This API is completely unstable and subject to change.
|
||||
extern crate syntax_pos;
|
||||
|
||||
extern crate arena;
|
||||
extern crate fmt_macros;
|
||||
#[macro_use] extern crate rustc;
|
||||
extern crate rustc_platform_intrinsics as intrinsics;
|
||||
extern crate rustc_back;
|
||||
|
Loading…
Reference in New Issue
Block a user