提交 c8a94c5d 编写于 作者: N Niko Matsakis

Convert TyPolyTraitRef to accept arbitary bounds, so that things like

`Box<for<'a> Foo<&'a T> + 'a>` can be accepted. Also cleanup the visitor/fold
in general, exposing more callbacks.
上级 9c808ffe
......@@ -5038,10 +5038,10 @@ fn resolve_type(&mut self, ty: &Ty) {
visit::walk_ty(self, ty);
}
TyPolyTraitRef(ref poly_trait_ref) => {
self.resolve_poly_trait_reference(
TyPolyTraitRef(ref bounds) => {
self.resolve_type_parameter_bounds(
ty.id,
&**poly_trait_ref,
bounds,
TraitObject);
visit::walk_ty(self, ty);
}
......
......@@ -883,15 +883,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ty::mk_closure(tcx, fn_decl)
}
ast::TyPolyTraitRef(ref data) => {
// FIXME(#18639) this is just a placeholder for code to come
let principal = instantiate_trait_ref(this, rscope, &data.trait_ref, None, None);
let bounds = conv_existential_bounds(this,
rscope,
ast_ty.span,
&[principal.clone()],
&[]);
ty::mk_trait(tcx, (*principal).clone(), bounds)
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
}
ast::TyPath(ref path, ref bounds, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
......@@ -1371,15 +1364,66 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
let ast_bound_refs: Vec<&ast::TyParamBound> =
ast_bounds.iter().collect();
let partitioned_bounds =
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
conv_existential_bounds_from_partitioned_bounds(
this, rscope, span, main_trait_refs, partitioned_bounds)
}
fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
this: &AC,
rscope: &RS,
span: Span,
ast_bounds: &[ast::TyParamBound])
-> ty::t
where AC: AstConv<'tcx>, RS:RegionScope
{
let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect();
let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
Some(trait_bound) => {
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
}
None => {
this.tcx().sess.span_err(
span,
"at least one non-builtin trait is required for an object type");
None
}
};
let bounds = conv_existential_bounds_from_partitioned_bounds(this,
rscope,
span,
main_trait_bound.as_slice(),
partitioned_bounds);
match main_trait_bound {
None => ty::mk_err(),
Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
}
}
pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
this: &AC,
rscope: &RS,
span: Span,
main_trait_refs: &[Rc<ty::TraitRef>],
partitioned_bounds: PartitionedBounds)
-> ty::ExistentialBounds
where AC: AstConv<'tcx>, RS:RegionScope
{
let PartitionedBounds { builtin_bounds,
trait_bounds,
region_bounds } =
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
partitioned_bounds;
if !trait_bounds.is_empty() {
let b = &trait_bounds[0];
this.tcx().sess.span_err(
b.path.span,
b.trait_ref.path.span,
format!("only the builtin traits can be used \
as closure or object bounds").as_slice());
}
......
......@@ -1154,7 +1154,7 @@ pub enum Ty_ {
/// Type parameters are stored in the Path itself
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(P<PolyTraitRef>),
TyPolyTraitRef(TyParamBounds),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
TyQPath(P<QPath>),
/// No-op; kept solely so that we can pretty-print faithfully
......
......@@ -494,10 +494,10 @@ fn visit_fn(&mut self,
}
visit::walk_fn(self,
function_kind,
function_declaration,
block,
span);
function_kind,
function_declaration,
block,
span);
if !self.pass_through_items {
match function_kind {
......
......@@ -445,10 +445,12 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
TyFixedLengthVec(ty, e) => {
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
}
TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
TyPolyTraitRef(poly_trait_ref) => {
TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p)))
},
TyTypeof(expr) => {
TyTypeof(fld.fold_expr(expr))
}
TyPolyTraitRef(bounds) => {
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
},
span: fld.new_span(span)
})
......
......@@ -1023,10 +1023,21 @@ pub fn parse_for_in_type(&mut self) -> Ty_ {
self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
} else if self.token == token::ModSep ||
self.token.is_ident() ||
self.token.is_path() {
self.token.is_path()
{
let trait_ref = self.parse_trait_ref();
TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs,
trait_ref: trait_ref }))
let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
trait_ref: trait_ref };
let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
self.parse_ty_param_bounds()
} else {
OwnedSlice::empty()
};
let all_bounds =
Some(TraitTyParamBound(poly_trait_ref)).into_iter()
.chain(other_bounds.into_vec().into_iter())
.collect();
ast::TyPolyTraitRef(all_bounds)
} else {
self.parse_ty_closure(lifetime_defs)
}
......
......@@ -739,8 +739,8 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
ast::TyPath(ref path, ref bounds, _) => {
try!(self.print_bounded_path(path, bounds));
}
ast::TyPolyTraitRef(ref poly_trait_ref) => {
try!(self.print_poly_trait_ref(&**poly_trait_ref));
ast::TyPolyTraitRef(ref bounds) => {
try!(self.print_bounds("", bounds));
}
ast::TyQPath(ref qpath) => {
try!(word(&mut self.s, "<"));
......
......@@ -78,6 +78,9 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _:
fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) }
fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) }
fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
walk_ty_param_bound(self, bounds)
}
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
walk_poly_trait_ref(self, t)
}
......@@ -119,6 +122,12 @@ fn visit_mac(&mut self, _macro: &'v Mac) {
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
walk_path_parameters(self, path_span, path_parameters)
}
fn visit_attribute(&mut self, _attr: &'v Attribute) {}
}
......@@ -170,7 +179,7 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
ViewPathGlob(ref path, id) => {
visitor.visit_path(path, id);
}
ViewPathList(ref path, ref list, _) => {
ViewPathList(ref prefix, ref list, _) => {
for id in list.iter() {
match id.node {
PathListIdent { name, .. } => {
......@@ -179,7 +188,10 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
PathListMod { .. } => ()
}
}
walk_path(visitor, path);
// Note that the `prefix` here is not a complete
// path, so we don't use `visit_path`.
walk_path(visitor, prefix);
}
}
}
......@@ -212,7 +224,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
trait_ref: &'v PolyTraitRef)
where V: Visitor<'v>
{
walk_lifetime_decls(visitor, &trait_ref.bound_lifetimes);
walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
visitor.visit_trait_ref(&trait_ref.trait_ref);
}
......@@ -290,7 +302,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
}
ItemTrait(ref generics, _, ref bounds, ref methods) => {
visitor.visit_generics(generics);
walk_ty_param_bounds(visitor, bounds);
walk_ty_param_bounds_helper(visitor, bounds);
for method in methods.iter() {
visitor.visit_trait_item(method)
}
......@@ -363,29 +375,29 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor.visit_ty(&*argument.ty)
}
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_ty_param_bounds(visitor, &function_declaration.bounds);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
}
TyProc(ref function_declaration) => {
for argument in function_declaration.decl.inputs.iter() {
visitor.visit_ty(&*argument.ty)
}
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_ty_param_bounds(visitor, &function_declaration.bounds);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
}
TyBareFn(ref function_declaration) => {
for argument in function_declaration.decl.inputs.iter() {
visitor.visit_ty(&*argument.ty)
}
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
}
TyPath(ref path, ref opt_bounds, id) => {
visitor.visit_path(path, id);
match *opt_bounds {
Some(ref bounds) => {
walk_ty_param_bounds(visitor, bounds);
walk_ty_param_bounds_helper(visitor, bounds);
}
None => { }
}
......@@ -399,8 +411,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor.visit_ty(&**ty);
visitor.visit_expr(&**expression)
}
TyPolyTraitRef(ref poly_trait_ref) => {
visitor.visit_poly_trait_ref(&**poly_trait_ref)
TyPolyTraitRef(ref bounds) => {
walk_ty_param_bounds_helper(visitor, bounds)
}
TyTypeof(ref expression) => {
visitor.visit_expr(&**expression)
......@@ -409,8 +421,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
}
fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V,
lifetimes: &'v Vec<LifetimeDef>) {
pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
lifetimes: &'v Vec<LifetimeDef>) {
for l in lifetimes.iter() {
visitor.visit_lifetime_decl(l);
}
......@@ -418,24 +430,35 @@ fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V,
pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
for segment in path.segments.iter() {
visitor.visit_ident(path.span, segment.identifier);
visitor.visit_path_segment(path.span, segment);
}
}
match segment.parameters {
ast::AngleBracketedParameters(ref data) => {
for typ in data.types.iter() {
visitor.visit_ty(&**typ);
}
for lifetime in data.lifetimes.iter() {
visitor.visit_lifetime_ref(lifetime);
}
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
visitor.visit_ident(path_span, segment.identifier);
visitor.visit_path_parameters(path_span, &segment.parameters);
}
pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
_path_span: Span,
path_parameters: &'v PathParameters) {
match *path_parameters {
ast::AngleBracketedParameters(ref data) => {
for typ in data.types.iter() {
visitor.visit_ty(&**typ);
}
ast::ParenthesizedParameters(ref data) => {
for typ in data.inputs.iter() {
visitor.visit_ty(&**typ);
}
for typ in data.output.iter() {
visitor.visit_ty(&**typ);
}
for lifetime in data.lifetimes.iter() {
visitor.visit_lifetime_ref(lifetime);
}
}
ast::ParenthesizedParameters(ref data) => {
for typ in data.inputs.iter() {
visitor.visit_ty(&**typ);
}
for typ in data.output.iter() {
visitor.visit_ty(&**typ);
}
}
}
......@@ -511,32 +534,37 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
}
}
pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
bounds: &'v OwnedSlice<TyParamBound>) {
pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
bounds: &'v OwnedSlice<TyParamBound>) {
for bound in bounds.iter() {
match *bound {
TraitTyParamBound(ref typ) => {
visitor.visit_poly_trait_ref(typ)
}
RegionTyParamBound(ref lifetime) => {
visitor.visit_lifetime_ref(lifetime);
}
visitor.visit_ty_param_bound(bound)
}
}
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
bound: &'v TyParamBound) {
match *bound {
TraitTyParamBound(ref typ) => {
visitor.visit_poly_trait_ref(typ);
}
RegionTyParamBound(ref lifetime) => {
visitor.visit_lifetime_ref(lifetime);
}
}
}
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
for type_parameter in generics.ty_params.iter() {
walk_ty_param_bounds(visitor, &type_parameter.bounds);
walk_ty_param_bounds_helper(visitor, &type_parameter.bounds);
match type_parameter.default {
Some(ref ty) => visitor.visit_ty(&**ty),
None => {}
}
}
walk_lifetime_decls(visitor, &generics.lifetimes);
walk_lifetime_decls_helper(visitor, &generics.lifetimes);
for predicate in generics.where_clause.predicates.iter() {
visitor.visit_ident(predicate.span, predicate.ident);
walk_ty_param_bounds(visitor, &predicate.bounds);
walk_ty_param_bounds_helper(visitor, &predicate.bounds);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册