AST/HIR: Merge ObjectSum and PolyTraitRef
This commit is contained in:
parent
828404684b
commit
2efe865d22
22 changed files with 119 additions and 240 deletions
|
@ -562,15 +562,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||||
TyPath(ref qpath) => {
|
TyPath(ref qpath) => {
|
||||||
visitor.visit_qpath(qpath, typ.id, typ.span);
|
visitor.visit_qpath(qpath, typ.id, typ.span);
|
||||||
}
|
}
|
||||||
TyObjectSum(ref ty, ref bounds) => {
|
|
||||||
visitor.visit_ty(ty);
|
|
||||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
|
||||||
}
|
|
||||||
TyArray(ref ty, length) => {
|
TyArray(ref ty, length) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visitor.visit_nested_body(length)
|
visitor.visit_nested_body(length)
|
||||||
}
|
}
|
||||||
TyPolyTraitRef(ref bounds) => {
|
TyObjectSum(ref bounds) => {
|
||||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||||
}
|
}
|
||||||
TyImplTrait(ref bounds) => {
|
TyImplTrait(ref bounds) => {
|
||||||
|
|
|
@ -308,9 +308,6 @@ impl<'a> LoweringContext<'a> {
|
||||||
span: t.span,
|
span: t.span,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
TyKind::ObjectSum(ref ty, ref bounds) => {
|
|
||||||
hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
|
|
||||||
}
|
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
let length = self.lower_expr(length);
|
let length = self.lower_expr(length);
|
||||||
hir::TyArray(self.lower_ty(ty),
|
hir::TyArray(self.lower_ty(ty),
|
||||||
|
@ -320,8 +317,8 @@ impl<'a> LoweringContext<'a> {
|
||||||
let expr = self.lower_expr(expr);
|
let expr = self.lower_expr(expr);
|
||||||
hir::TyTypeof(self.record_body(expr, None))
|
hir::TyTypeof(self.record_body(expr, None))
|
||||||
}
|
}
|
||||||
TyKind::PolyTraitRef(ref bounds) => {
|
TyKind::ObjectSum(ref bounds) => {
|
||||||
hir::TyPolyTraitRef(self.lower_bounds(bounds))
|
hir::TyObjectSum(self.lower_bounds(bounds))
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(ref bounds) => {
|
TyKind::ImplTrait(ref bounds) => {
|
||||||
hir::TyImplTrait(self.lower_bounds(bounds))
|
hir::TyImplTrait(self.lower_bounds(bounds))
|
||||||
|
|
|
@ -1214,12 +1214,11 @@ pub enum Ty_ {
|
||||||
///
|
///
|
||||||
/// Type parameters may be stored in each `PathSegment`.
|
/// Type parameters may be stored in each `PathSegment`.
|
||||||
TyPath(QPath),
|
TyPath(QPath),
|
||||||
|
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||||
/// Something like `A+B`. Note that `B` must always be a path.
|
/// where `Bound` is a trait or a lifetime.
|
||||||
TyObjectSum(P<Ty>, TyParamBounds),
|
TyObjectSum(TyParamBounds),
|
||||||
/// A type like `for<'a> Foo<&'a Bar>`
|
/// An `impl Bound1 + Bound2 + Bound3` type
|
||||||
TyPolyTraitRef(TyParamBounds),
|
/// where `Bound` is a trait or a lifetime.
|
||||||
/// An `impl TraitA+TraitB` type.
|
|
||||||
TyImplTrait(TyParamBounds),
|
TyImplTrait(TyParamBounds),
|
||||||
/// Unused for now
|
/// Unused for now
|
||||||
TyTypeof(BodyId),
|
TyTypeof(BodyId),
|
||||||
|
|
|
@ -418,11 +418,7 @@ impl<'a> State<'a> {
|
||||||
hir::TyPath(ref qpath) => {
|
hir::TyPath(ref qpath) => {
|
||||||
self.print_qpath(qpath, false)?
|
self.print_qpath(qpath, false)?
|
||||||
}
|
}
|
||||||
hir::TyObjectSum(ref ty, ref bounds) => {
|
hir::TyObjectSum(ref bounds) => {
|
||||||
self.print_type(&ty)?;
|
|
||||||
self.print_bounds("+", &bounds[..])?;
|
|
||||||
}
|
|
||||||
hir::TyPolyTraitRef(ref bounds) => {
|
|
||||||
self.print_bounds("", &bounds[..])?;
|
self.print_bounds("", &bounds[..])?;
|
||||||
}
|
}
|
||||||
hir::TyImplTrait(ref bounds) => {
|
hir::TyImplTrait(ref bounds) => {
|
||||||
|
|
|
@ -441,7 +441,6 @@ enum SawTyComponent {
|
||||||
SawTyTup,
|
SawTyTup,
|
||||||
SawTyPath,
|
SawTyPath,
|
||||||
SawTyObjectSum,
|
SawTyObjectSum,
|
||||||
SawTyPolyTraitRef,
|
|
||||||
SawTyImplTrait,
|
SawTyImplTrait,
|
||||||
SawTyTypeof,
|
SawTyTypeof,
|
||||||
SawTyInfer
|
SawTyInfer
|
||||||
|
@ -458,7 +457,6 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
|
||||||
TyTup(..) => SawTyTup,
|
TyTup(..) => SawTyTup,
|
||||||
TyPath(_) => SawTyPath,
|
TyPath(_) => SawTyPath,
|
||||||
TyObjectSum(..) => SawTyObjectSum,
|
TyObjectSum(..) => SawTyObjectSum,
|
||||||
TyPolyTraitRef(..) => SawTyPolyTraitRef,
|
|
||||||
TyImplTrait(..) => SawTyImplTrait,
|
TyImplTrait(..) => SawTyImplTrait,
|
||||||
TyTypeof(..) => SawTyTypeof,
|
TyTypeof(..) => SawTyTypeof,
|
||||||
TyInfer => SawTyInfer
|
TyInfer => SawTyInfer
|
||||||
|
|
|
@ -143,8 +143,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
err.emit();
|
err.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TyKind::ObjectSum(_, ref bounds) |
|
TyKind::ObjectSum(ref bounds) => {
|
||||||
TyKind::PolyTraitRef(ref bounds) => {
|
|
||||||
self.no_questions_in_bounds(bounds, "trait object types", false);
|
self.no_questions_in_bounds(bounds, "trait object types", false);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -73,7 +73,7 @@ use std::iter;
|
||||||
use syntax::{abi, ast};
|
use syntax::{abi, ast};
|
||||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
use syntax_pos::{Span, Pos};
|
use syntax_pos::Span;
|
||||||
use errors::DiagnosticBuilder;
|
use errors::DiagnosticBuilder;
|
||||||
|
|
||||||
pub trait AstConv<'gcx, 'tcx> {
|
pub trait AstConv<'gcx, 'tcx> {
|
||||||
|
@ -930,87 +930,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
decl_ty.subst(self.tcx(), substs)
|
decl_ty.subst(self.tcx(), substs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ast_ty_to_object_trait_ref(&self,
|
|
||||||
rscope: &RegionScope,
|
|
||||||
span: Span,
|
|
||||||
ty: &hir::Ty,
|
|
||||||
bounds: &[hir::TyParamBound])
|
|
||||||
-> Ty<'tcx>
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* In a type like `Foo + Send`, we want to wait to collect the
|
|
||||||
* full set of bounds before we make the object type, because we
|
|
||||||
* need them to infer a region bound. (For example, if we tried
|
|
||||||
* made a type from just `Foo`, then it wouldn't be enough to
|
|
||||||
* infer a 'static bound, and hence the user would get an error.)
|
|
||||||
* So this function is used when we're dealing with a sum type to
|
|
||||||
* convert the LHS. It only accepts a type that refers to a trait
|
|
||||||
* name, and reports an error otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let tcx = self.tcx();
|
|
||||||
match ty.node {
|
|
||||||
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
|
|
||||||
if let Def::Trait(trait_def_id) = path.def {
|
|
||||||
self.trait_path_to_object_type(rscope,
|
|
||||||
path.span,
|
|
||||||
trait_def_id,
|
|
||||||
ty.id,
|
|
||||||
path.segments.last().unwrap(),
|
|
||||||
span,
|
|
||||||
partition_bounds(bounds))
|
|
||||||
} else {
|
|
||||||
struct_span_err!(tcx.sess, ty.span, E0172,
|
|
||||||
"expected a reference to a trait")
|
|
||||||
.span_label(ty.span, &format!("expected a trait"))
|
|
||||||
.emit();
|
|
||||||
tcx.types.err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let mut err = struct_span_err!(tcx.sess, ty.span, E0178,
|
|
||||||
"expected a path on the left-hand side \
|
|
||||||
of `+`, not `{}`",
|
|
||||||
tcx.map.node_to_pretty_string(ty.id));
|
|
||||||
err.span_label(ty.span, &format!("expected a path"));
|
|
||||||
let hi = bounds.iter().map(|x| match *x {
|
|
||||||
hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
|
|
||||||
hir::RegionTyParamBound(ref r) => r.span.hi,
|
|
||||||
}).max_by_key(|x| x.to_usize());
|
|
||||||
let full_span = hi.map(|hi| Span {
|
|
||||||
lo: ty.span.lo,
|
|
||||||
hi: hi,
|
|
||||||
expn_id: ty.span.expn_id,
|
|
||||||
});
|
|
||||||
match (&ty.node, full_span) {
|
|
||||||
(&hir::TyRptr(ref lifetime, ref mut_ty), Some(full_span)) => {
|
|
||||||
let ty_str = hir::print::to_string(&tcx.map, |s| {
|
|
||||||
use syntax::print::pp::word;
|
|
||||||
use syntax::print::pprust::PrintState;
|
|
||||||
|
|
||||||
word(&mut s.s, "&")?;
|
|
||||||
s.print_opt_lifetime(lifetime)?;
|
|
||||||
s.print_mutability(mut_ty.mutbl)?;
|
|
||||||
s.popen()?;
|
|
||||||
s.print_type(&mut_ty.ty)?;
|
|
||||||
s.print_bounds(" +", bounds)?;
|
|
||||||
s.pclose()
|
|
||||||
});
|
|
||||||
err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
|
|
||||||
ty_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
help!(&mut err,
|
|
||||||
"perhaps you forgot parentheses? (per RFC 438)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
tcx.types.err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transform a PolyTraitRef into a PolyExistentialTraitRef by
|
/// Transform a PolyTraitRef into a PolyExistentialTraitRef by
|
||||||
/// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
|
/// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
|
||||||
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
|
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
|
||||||
|
@ -1534,9 +1453,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
hir::TySlice(ref ty) => {
|
hir::TySlice(ref ty) => {
|
||||||
tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
|
tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
|
||||||
}
|
}
|
||||||
hir::TyObjectSum(ref ty, ref bounds) => {
|
|
||||||
self.ast_ty_to_object_trait_ref(rscope, ast_ty.span, ty, bounds)
|
|
||||||
}
|
|
||||||
hir::TyPtr(ref mt) => {
|
hir::TyPtr(ref mt) => {
|
||||||
tcx.mk_ptr(ty::TypeAndMut {
|
tcx.mk_ptr(ty::TypeAndMut {
|
||||||
ty: self.ast_ty_to_ty(rscope, &mt.ty),
|
ty: self.ast_ty_to_ty(rscope, &mt.ty),
|
||||||
|
@ -1609,7 +1525,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
}
|
}
|
||||||
tcx.mk_fn_ptr(bare_fn_ty)
|
tcx.mk_fn_ptr(bare_fn_ty)
|
||||||
}
|
}
|
||||||
hir::TyPolyTraitRef(ref bounds) => {
|
hir::TyObjectSum(ref bounds) => {
|
||||||
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
|
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
|
||||||
}
|
}
|
||||||
hir::TyImplTrait(ref bounds) => {
|
hir::TyImplTrait(ref bounds) => {
|
||||||
|
|
|
@ -1864,55 +1864,6 @@ fn bar(foo: Foo) -> u32 {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0172: r##"
|
|
||||||
This error means that an attempt was made to specify the type of a variable with
|
|
||||||
a combination of a concrete type and a trait. Consider the following example:
|
|
||||||
|
|
||||||
```compile_fail,E0172
|
|
||||||
fn foo(bar: i32+std::fmt::Display) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
The code is trying to specify that we want to receive a signed 32-bit integer
|
|
||||||
which also implements `Display`. This doesn't make sense: when we pass `i32`, a
|
|
||||||
concrete type, it implicitly includes all of the traits that it implements.
|
|
||||||
This includes `Display`, `Debug`, `Clone`, and a host of others.
|
|
||||||
|
|
||||||
If `i32` implements the trait we desire, there's no need to specify the trait
|
|
||||||
separately. If it does not, then we need to `impl` the trait for `i32` before
|
|
||||||
passing it into `foo`. Either way, a fixed definition for `foo` will look like
|
|
||||||
the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
fn foo(bar: i32) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
To learn more about traits, take a look at the Book:
|
|
||||||
|
|
||||||
https://doc.rust-lang.org/book/traits.html
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0178: r##"
|
|
||||||
In types, the `+` type operator has low precedence, so it is often necessary
|
|
||||||
to use parentheses.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```compile_fail,E0178
|
|
||||||
trait Foo {}
|
|
||||||
|
|
||||||
struct Bar<'a> {
|
|
||||||
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
|
|
||||||
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
|
|
||||||
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
|
|
||||||
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
More details can be found in [RFC 438].
|
|
||||||
|
|
||||||
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0182: r##"
|
E0182: r##"
|
||||||
You bound an associated type in an expression path which is not
|
You bound an associated type in an expression path which is not
|
||||||
allowed.
|
allowed.
|
||||||
|
@ -4152,6 +4103,7 @@ register_diagnostics! {
|
||||||
// E0163, // merged into E0071
|
// E0163, // merged into E0071
|
||||||
// E0167,
|
// E0167,
|
||||||
// E0168,
|
// E0168,
|
||||||
|
// E0172, // non-trait found in a type sum, moved to resolve
|
||||||
// E0173, // manual implementations of unboxed closure traits are experimental
|
// E0173, // manual implementations of unboxed closure traits are experimental
|
||||||
// E0174,
|
// E0174,
|
||||||
E0183,
|
E0183,
|
||||||
|
|
|
@ -1504,9 +1504,6 @@ pub enum Type {
|
||||||
// _
|
// _
|
||||||
Infer,
|
Infer,
|
||||||
|
|
||||||
// for<'a> Foo(&'a)
|
|
||||||
PolyTraitRef(Vec<TyParamBound>),
|
|
||||||
|
|
||||||
// impl TraitA+TraitB
|
// impl TraitA+TraitB
|
||||||
ImplTrait(Vec<TyParamBound>),
|
ImplTrait(Vec<TyParamBound>),
|
||||||
}
|
}
|
||||||
|
@ -1768,24 +1765,26 @@ impl Clean<Type> for hir::Ty {
|
||||||
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
|
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyObjectSum(ref lhs, ref bounds) => {
|
TyObjectSum(ref bounds) => {
|
||||||
let lhs_ty = lhs.clean(cx);
|
let lhs_ty = bounds[0].clean(cx);
|
||||||
match lhs_ty {
|
match lhs_ty {
|
||||||
ResolvedPath { path, typarams: None, did, is_generic } => {
|
TraitBound(poly_trait, ..) => {
|
||||||
ResolvedPath {
|
match poly_trait.trait_ {
|
||||||
path: path,
|
ResolvedPath { path, typarams: None, did, is_generic } => {
|
||||||
typarams: Some(bounds.clean(cx)),
|
ResolvedPath {
|
||||||
did: did,
|
path: path,
|
||||||
is_generic: is_generic,
|
typarams: Some(bounds[1..].clean(cx)),
|
||||||
|
did: did,
|
||||||
|
is_generic: is_generic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Infer // shouldn't happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => Infer // shouldn't happen
|
||||||
lhs_ty // shouldn't happen
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
||||||
TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
|
|
||||||
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
|
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
|
||||||
TyInfer => Infer,
|
TyInfer => Infer,
|
||||||
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
|
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
|
||||||
|
|
|
@ -679,19 +679,6 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean::PolyTraitRef(ref bounds) => {
|
|
||||||
for (i, bound) in bounds.iter().enumerate() {
|
|
||||||
if i != 0 {
|
|
||||||
write!(f, " + ")?;
|
|
||||||
}
|
|
||||||
if f.alternate() {
|
|
||||||
write!(f, "{:#}", *bound)?;
|
|
||||||
} else {
|
|
||||||
write!(f, "{}", *bound)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
clean::ImplTrait(ref bounds) => {
|
clean::ImplTrait(ref bounds) => {
|
||||||
write!(f, "impl ")?;
|
write!(f, "impl ")?;
|
||||||
for (i, bound) in bounds.iter().enumerate() {
|
for (i, bound) in bounds.iter().enumerate() {
|
||||||
|
|
|
@ -1357,11 +1357,11 @@ pub enum TyKind {
|
||||||
///
|
///
|
||||||
/// Type parameters are stored in the Path itself
|
/// Type parameters are stored in the Path itself
|
||||||
Path(Option<QSelf>, Path),
|
Path(Option<QSelf>, Path),
|
||||||
/// Something like `A+B`. Note that `B` must always be a path.
|
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||||
ObjectSum(P<Ty>, TyParamBounds),
|
/// where `Bound` is a trait or a lifetime.
|
||||||
/// A type like `for<'a> Foo<&'a Bar>`
|
ObjectSum(TyParamBounds),
|
||||||
PolyTraitRef(TyParamBounds),
|
/// An `impl Bound1 + Bound2 + Bound3` type
|
||||||
/// An `impl TraitA+TraitB` type.
|
/// where `Bound` is a trait or a lifetime.
|
||||||
ImplTrait(TyParamBounds),
|
ImplTrait(TyParamBounds),
|
||||||
/// No-op; kept solely so that we can pretty-print faithfully
|
/// No-op; kept solely so that we can pretty-print faithfully
|
||||||
Paren(P<Ty>),
|
Paren(P<Ty>),
|
||||||
|
|
|
@ -15,6 +15,28 @@
|
||||||
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
|
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
|
||||||
register_long_diagnostics! {
|
register_long_diagnostics! {
|
||||||
|
|
||||||
|
E0178: r##"
|
||||||
|
In types, the `+` type operator has low precedence, so it is often necessary
|
||||||
|
to use parentheses.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```compile_fail,E0178
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
struct Bar<'a> {
|
||||||
|
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
|
||||||
|
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
|
||||||
|
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
|
||||||
|
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
More details can be found in [RFC 438].
|
||||||
|
|
||||||
|
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
|
||||||
|
"##,
|
||||||
|
|
||||||
E0534: r##"
|
E0534: r##"
|
||||||
The `inline` attribute was malformed.
|
The `inline` attribute was malformed.
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ pub trait AstBuilder {
|
||||||
|
|
||||||
fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty>;
|
fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty>;
|
||||||
fn ty_path(&self, ast::Path) -> P<ast::Ty>;
|
fn ty_path(&self, ast::Path) -> P<ast::Ty>;
|
||||||
fn ty_sum(&self, ast::Path, ast::TyParamBounds) -> P<ast::Ty>;
|
|
||||||
fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
|
fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
|
||||||
|
|
||||||
fn ty_rptr(&self, span: Span,
|
fn ty_rptr(&self, span: Span,
|
||||||
|
@ -403,12 +402,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
self.ty(path.span, ast::TyKind::Path(None, path))
|
self.ty(path.span, ast::TyKind::Path(None, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_sum(&self, path: ast::Path, bounds: ast::TyParamBounds) -> P<ast::Ty> {
|
|
||||||
self.ty(path.span,
|
|
||||||
ast::TyKind::ObjectSum(self.ty_path(path),
|
|
||||||
bounds))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Might need to take bounds as an argument in the future, if you ever want
|
// Might need to take bounds as an argument in the future, if you ever want
|
||||||
// to generate a bounded existential trait type.
|
// to generate a bounded existential trait type.
|
||||||
fn ty_ident(&self, span: Span, ident: ast::Ident)
|
fn ty_ident(&self, span: Span, ident: ast::Ident)
|
||||||
|
|
|
@ -380,18 +380,14 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
});
|
});
|
||||||
TyKind::Path(qself, fld.fold_path(path))
|
TyKind::Path(qself, fld.fold_path(path))
|
||||||
}
|
}
|
||||||
TyKind::ObjectSum(ty, bounds) => {
|
|
||||||
TyKind::ObjectSum(fld.fold_ty(ty),
|
|
||||||
fld.fold_bounds(bounds))
|
|
||||||
}
|
|
||||||
TyKind::Array(ty, e) => {
|
TyKind::Array(ty, e) => {
|
||||||
TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e))
|
TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e))
|
||||||
}
|
}
|
||||||
TyKind::Typeof(expr) => {
|
TyKind::Typeof(expr) => {
|
||||||
TyKind::Typeof(fld.fold_expr(expr))
|
TyKind::Typeof(fld.fold_expr(expr))
|
||||||
}
|
}
|
||||||
TyKind::PolyTraitRef(bounds) => {
|
TyKind::ObjectSum(bounds) => {
|
||||||
TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
|
TyKind::ObjectSum(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(bounds) => {
|
TyKind::ImplTrait(bounds) => {
|
||||||
TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
|
TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
|
||||||
|
|
|
@ -40,7 +40,7 @@ use ast::{Visibility, WhereClause};
|
||||||
use ast::{BinOpKind, UnOp};
|
use ast::{BinOpKind, UnOp};
|
||||||
use {ast, attr};
|
use {ast, attr};
|
||||||
use codemap::{self, CodeMap, Spanned, spanned, respan};
|
use codemap::{self, CodeMap, Spanned, spanned, respan};
|
||||||
use syntax_pos::{self, Span, BytePos, mk_sp};
|
use syntax_pos::{self, Span, Pos, BytePos, mk_sp};
|
||||||
use errors::{self, DiagnosticBuilder};
|
use errors::{self, DiagnosticBuilder};
|
||||||
use ext::tt::macro_parser;
|
use ext::tt::macro_parser;
|
||||||
use parse;
|
use parse;
|
||||||
|
@ -1045,7 +1045,7 @@ impl<'a> Parser<'a> {
|
||||||
Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
|
Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
|
||||||
.chain(other_bounds.into_vec())
|
.chain(other_bounds.into_vec())
|
||||||
.collect();
|
.collect();
|
||||||
Ok(ast::TyKind::PolyTraitRef(all_bounds))
|
Ok(ast::TyKind::ObjectSum(all_bounds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,7 +1267,7 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(lhs);
|
return Ok(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
let bounds = self.parse_ty_param_bounds()?;
|
let mut bounds = self.parse_ty_param_bounds()?.into_vec();
|
||||||
|
|
||||||
// In type grammar, `+` is treated like a binary operator,
|
// In type grammar, `+` is treated like a binary operator,
|
||||||
// and hence both L and R side are required.
|
// and hence both L and R side are required.
|
||||||
|
@ -1277,9 +1277,57 @@ impl<'a> Parser<'a> {
|
||||||
"at least one type parameter bound \
|
"at least one type parameter bound \
|
||||||
must be specified");
|
must be specified");
|
||||||
}
|
}
|
||||||
|
if let TyKind::Path(None, ref path) = lhs.node {
|
||||||
|
let poly_trait_ref = PolyTraitRef {
|
||||||
|
bound_lifetimes: Vec::new(),
|
||||||
|
trait_ref: TraitRef { path: path.clone(), ref_id: lhs.id },
|
||||||
|
span: lhs.span,
|
||||||
|
};
|
||||||
|
let poly_trait_ref = TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None);
|
||||||
|
bounds.insert(0, poly_trait_ref);
|
||||||
|
} else {
|
||||||
|
let mut err = struct_span_err!(self.sess.span_diagnostic, lhs.span, E0178,
|
||||||
|
"expected a path on the left-hand side \
|
||||||
|
of `+`, not `{}`",
|
||||||
|
pprust::ty_to_string(&lhs));
|
||||||
|
err.span_label(lhs.span, &format!("expected a path"));
|
||||||
|
let hi = bounds.iter().map(|x| match *x {
|
||||||
|
ast::TraitTyParamBound(ref tr, _) => tr.span.hi,
|
||||||
|
ast::RegionTyParamBound(ref r) => r.span.hi,
|
||||||
|
}).max_by_key(|x| x.to_usize());
|
||||||
|
let full_span = hi.map(|hi| Span {
|
||||||
|
lo: lhs.span.lo,
|
||||||
|
hi: hi,
|
||||||
|
expn_id: lhs.span.expn_id,
|
||||||
|
});
|
||||||
|
match (&lhs.node, full_span) {
|
||||||
|
(&TyKind::Rptr(ref lifetime, ref mut_ty), Some(full_span)) => {
|
||||||
|
let ty_str = pprust::to_string(|s| {
|
||||||
|
use print::pp::word;
|
||||||
|
use print::pprust::PrintState;
|
||||||
|
|
||||||
|
word(&mut s.s, "&")?;
|
||||||
|
s.print_opt_lifetime(lifetime)?;
|
||||||
|
s.print_mutability(mut_ty.mutbl)?;
|
||||||
|
s.popen()?;
|
||||||
|
s.print_type(&mut_ty.ty)?;
|
||||||
|
s.print_bounds(" +", &bounds)?;
|
||||||
|
s.pclose()
|
||||||
|
});
|
||||||
|
err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
|
||||||
|
ty_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
help!(&mut err,
|
||||||
|
"perhaps you forgot parentheses? (per RFC 438)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
|
||||||
let sp = mk_sp(lo, self.prev_span.hi);
|
let sp = mk_sp(lo, self.prev_span.hi);
|
||||||
let sum = ast::TyKind::ObjectSum(lhs, bounds);
|
let sum = TyKind::ObjectSum(bounds.into());
|
||||||
Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
|
Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1028,11 +1028,7 @@ impl<'a> State<'a> {
|
||||||
ast::TyKind::Path(Some(ref qself), ref path) => {
|
ast::TyKind::Path(Some(ref qself), ref path) => {
|
||||||
self.print_qpath(path, qself, false)?
|
self.print_qpath(path, qself, false)?
|
||||||
}
|
}
|
||||||
ast::TyKind::ObjectSum(ref ty, ref bounds) => {
|
ast::TyKind::ObjectSum(ref bounds) => {
|
||||||
self.print_type(&ty)?;
|
|
||||||
self.print_bounds("+", &bounds[..])?;
|
|
||||||
}
|
|
||||||
ast::TyKind::PolyTraitRef(ref bounds) => {
|
|
||||||
self.print_bounds("", &bounds[..])?;
|
self.print_bounds("", &bounds[..])?;
|
||||||
}
|
}
|
||||||
ast::TyKind::ImplTrait(ref bounds) => {
|
ast::TyKind::ImplTrait(ref bounds) => {
|
||||||
|
|
|
@ -342,15 +342,11 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||||
}
|
}
|
||||||
visitor.visit_path(path, typ.id);
|
visitor.visit_path(path, typ.id);
|
||||||
}
|
}
|
||||||
TyKind::ObjectSum(ref ty, ref bounds) => {
|
|
||||||
visitor.visit_ty(ty);
|
|
||||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
|
||||||
}
|
|
||||||
TyKind::Array(ref ty, ref expression) => {
|
TyKind::Array(ref ty, ref expression) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visitor.visit_expr(expression)
|
visitor.visit_expr(expression)
|
||||||
}
|
}
|
||||||
TyKind::PolyTraitRef(ref bounds) => {
|
TyKind::ObjectSum(ref bounds) => {
|
||||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(ref bounds) => {
|
TyKind::ImplTrait(ref bounds) => {
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
fn foo(bar: i32+std::fmt::Display) {}
|
|
||||||
//~^ ERROR E0172
|
|
||||||
//~| NOTE expected a trait
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
}
|
|
|
@ -17,12 +17,15 @@ struct Bar<'a> {
|
||||||
x: &'a Foo + 'a,
|
x: &'a Foo + 'a,
|
||||||
//~^ ERROR E0178
|
//~^ ERROR E0178
|
||||||
//~| NOTE expected a path
|
//~| NOTE expected a path
|
||||||
|
//~| ERROR at least one non-builtin trait is required for an object type
|
||||||
y: &'a mut Foo + 'a,
|
y: &'a mut Foo + 'a,
|
||||||
//~^ ERROR E0178
|
//~^ ERROR E0178
|
||||||
//~| NOTE expected a path
|
//~| NOTE expected a path
|
||||||
|
//~| ERROR at least one non-builtin trait is required for an object type
|
||||||
z: fn() -> Foo + 'a,
|
z: fn() -> Foo + 'a,
|
||||||
//~^ ERROR E0178
|
//~^ ERROR E0178
|
||||||
//~| NOTE expected a path
|
//~| NOTE expected a path
|
||||||
|
//~| ERROR at least one non-builtin trait is required for an object type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected a reference to a trait
|
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -13,8 +13,10 @@ fn main() {
|
||||||
//~^ ERROR expected a path
|
//~^ ERROR expected a path
|
||||||
//~| HELP try adding parentheses
|
//~| HELP try adding parentheses
|
||||||
//~| SUGGESTION let _: &(Copy + 'static);
|
//~| SUGGESTION let _: &(Copy + 'static);
|
||||||
|
//~| ERROR at least one non-builtin trait is required for an object type
|
||||||
let _: &'static Copy + 'static;
|
let _: &'static Copy + 'static;
|
||||||
//~^ ERROR expected a path
|
//~^ ERROR expected a path
|
||||||
//~| HELP try adding parentheses
|
//~| HELP try adding parentheses
|
||||||
//~| SUGGESTION let _: &'static (Copy + 'static);
|
//~| SUGGESTION let _: &'static (Copy + 'static);
|
||||||
|
//~| ERROR at least one non-builtin trait is required for an object type
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ trait Tr {
|
||||||
}
|
}
|
||||||
impl Tr for isize { }
|
impl Tr for isize { }
|
||||||
|
|
||||||
fn foo<'a>(x: Box<Tr+ Sync + 'a>) -> Box<Tr+ Sync + 'a> { x }
|
fn foo<'a>(x: Box< Tr + Sync + 'a>) -> Box< Tr + Sync + 'a> { x }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: Box<Tr+ Sync>;
|
let x: Box< Tr + Sync>;
|
||||||
|
|
||||||
Box::new(1isize) as Box<Tr+ Sync>;
|
Box::new(1isize) as Box< Tr + Sync>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue