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.
This commit is contained in:
parent
9c808ffee4
commit
c8a94c5dfa
8 changed files with 155 additions and 70 deletions
|
|
@ -5038,10 +5038,10 @@ impl<'a> Resolver<'a> {
|
|||
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 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
|
|||
}
|
||||
|
||||
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 @@ impl<'a> Parser<'a> {
|
|||
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 @@ impl<'a> State<'a> {
|
|||
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 @@ pub trait Visitor<'v> {
|
|||
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 @@ pub trait Visitor<'v> {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue