Skip to content

Commit c8a94c5

Browse files
committed
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.
1 parent 9c808ff commit c8a94c5

File tree

8 files changed

+155
-70
lines changed

8 files changed

+155
-70
lines changed

src/librustc/middle/resolve.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5038,10 +5038,10 @@ impl<'a> Resolver<'a> {
50385038
visit::walk_ty(self, ty);
50395039
}
50405040

5041-
TyPolyTraitRef(ref poly_trait_ref) => {
5042-
self.resolve_poly_trait_reference(
5041+
TyPolyTraitRef(ref bounds) => {
5042+
self.resolve_type_parameter_bounds(
50435043
ty.id,
5044-
&**poly_trait_ref,
5044+
bounds,
50455045
TraitObject);
50465046
visit::walk_ty(self, ty);
50475047
}

src/librustc/middle/typeck/astconv.rs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -883,15 +883,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
883883

884884
ty::mk_closure(tcx, fn_decl)
885885
}
886-
ast::TyPolyTraitRef(ref data) => {
887-
// FIXME(#18639) this is just a placeholder for code to come
888-
let principal = instantiate_trait_ref(this, rscope, &data.trait_ref, None, None);
889-
let bounds = conv_existential_bounds(this,
890-
rscope,
891-
ast_ty.span,
892-
&[principal.clone()],
893-
&[]);
894-
ty::mk_trait(tcx, (*principal).clone(), bounds)
886+
ast::TyPolyTraitRef(ref bounds) => {
887+
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
895888
}
896889
ast::TyPath(ref path, ref bounds, id) => {
897890
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>(
13711364
let ast_bound_refs: Vec<&ast::TyParamBound> =
13721365
ast_bounds.iter().collect();
13731366

1367+
let partitioned_bounds =
1368+
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
1369+
1370+
conv_existential_bounds_from_partitioned_bounds(
1371+
this, rscope, span, main_trait_refs, partitioned_bounds)
1372+
}
1373+
1374+
fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
1375+
this: &AC,
1376+
rscope: &RS,
1377+
span: Span,
1378+
ast_bounds: &[ast::TyParamBound])
1379+
-> ty::t
1380+
where AC: AstConv<'tcx>, RS:RegionScope
1381+
{
1382+
let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect();
1383+
let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
1384+
1385+
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
1386+
Some(trait_bound) => {
1387+
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
1388+
}
1389+
None => {
1390+
this.tcx().sess.span_err(
1391+
span,
1392+
"at least one non-builtin trait is required for an object type");
1393+
None
1394+
}
1395+
};
1396+
1397+
let bounds = conv_existential_bounds_from_partitioned_bounds(this,
1398+
rscope,
1399+
span,
1400+
main_trait_bound.as_slice(),
1401+
partitioned_bounds);
1402+
1403+
match main_trait_bound {
1404+
None => ty::mk_err(),
1405+
Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
1406+
}
1407+
}
1408+
1409+
pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
1410+
this: &AC,
1411+
rscope: &RS,
1412+
span: Span,
1413+
main_trait_refs: &[Rc<ty::TraitRef>],
1414+
partitioned_bounds: PartitionedBounds)
1415+
-> ty::ExistentialBounds
1416+
where AC: AstConv<'tcx>, RS:RegionScope
1417+
{
13741418
let PartitionedBounds { builtin_bounds,
13751419
trait_bounds,
13761420
region_bounds } =
1377-
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
1421+
partitioned_bounds;
13781422

13791423
if !trait_bounds.is_empty() {
13801424
let b = &trait_bounds[0];
13811425
this.tcx().sess.span_err(
1382-
b.path.span,
1426+
b.trait_ref.path.span,
13831427
format!("only the builtin traits can be used \
13841428
as closure or object bounds").as_slice());
13851429
}

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ pub enum Ty_ {
11541154
/// Type parameters are stored in the Path itself
11551155
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
11561156
/// A type like `for<'a> Foo<&'a Bar>`
1157-
TyPolyTraitRef(P<PolyTraitRef>),
1157+
TyPolyTraitRef(TyParamBounds),
11581158
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
11591159
TyQPath(P<QPath>),
11601160
/// No-op; kept solely so that we can pretty-print faithfully

src/libsyntax/ast_util.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,10 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
494494
}
495495

496496
visit::walk_fn(self,
497-
function_kind,
498-
function_declaration,
499-
block,
500-
span);
497+
function_kind,
498+
function_declaration,
499+
block,
500+
span);
501501

502502
if !self.pass_through_items {
503503
match function_kind {

src/libsyntax/fold.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,10 +445,12 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
445445
TyFixedLengthVec(ty, e) => {
446446
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
447447
}
448-
TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
449-
TyPolyTraitRef(poly_trait_ref) => {
450-
TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p)))
451-
},
448+
TyTypeof(expr) => {
449+
TyTypeof(fld.fold_expr(expr))
450+
}
451+
TyPolyTraitRef(bounds) => {
452+
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
453+
}
452454
},
453455
span: fld.new_span(span)
454456
})

src/libsyntax/parse/parser.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,10 +1023,21 @@ impl<'a> Parser<'a> {
10231023
self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
10241024
} else if self.token == token::ModSep ||
10251025
self.token.is_ident() ||
1026-
self.token.is_path() {
1026+
self.token.is_path()
1027+
{
10271028
let trait_ref = self.parse_trait_ref();
1028-
TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs,
1029-
trait_ref: trait_ref }))
1029+
let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
1030+
trait_ref: trait_ref };
1031+
let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
1032+
self.parse_ty_param_bounds()
1033+
} else {
1034+
OwnedSlice::empty()
1035+
};
1036+
let all_bounds =
1037+
Some(TraitTyParamBound(poly_trait_ref)).into_iter()
1038+
.chain(other_bounds.into_vec().into_iter())
1039+
.collect();
1040+
ast::TyPolyTraitRef(all_bounds)
10301041
} else {
10311042
self.parse_ty_closure(lifetime_defs)
10321043
}

src/libsyntax/print/pprust.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,8 @@ impl<'a> State<'a> {
739739
ast::TyPath(ref path, ref bounds, _) => {
740740
try!(self.print_bounded_path(path, bounds));
741741
}
742-
ast::TyPolyTraitRef(ref poly_trait_ref) => {
743-
try!(self.print_poly_trait_ref(&**poly_trait_ref));
742+
ast::TyPolyTraitRef(ref bounds) => {
743+
try!(self.print_bounds("", bounds));
744744
}
745745
ast::TyQPath(ref qpath) => {
746746
try!(word(&mut self.s, "<"));

src/libsyntax/visit.rs

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ pub trait Visitor<'v> {
7878
fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) }
7979
fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) }
8080
fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
81+
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
82+
walk_ty_param_bound(self, bounds)
83+
}
8184
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
8285
walk_poly_trait_ref(self, t)
8386
}
@@ -119,6 +122,12 @@ pub trait Visitor<'v> {
119122
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
120123
walk_path(self, path)
121124
}
125+
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
126+
walk_path_segment(self, path_span, path_segment)
127+
}
128+
fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
129+
walk_path_parameters(self, path_span, path_parameters)
130+
}
122131
fn visit_attribute(&mut self, _attr: &'v Attribute) {}
123132
}
124133

@@ -170,7 +179,7 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
170179
ViewPathGlob(ref path, id) => {
171180
visitor.visit_path(path, id);
172181
}
173-
ViewPathList(ref path, ref list, _) => {
182+
ViewPathList(ref prefix, ref list, _) => {
174183
for id in list.iter() {
175184
match id.node {
176185
PathListIdent { name, .. } => {
@@ -179,7 +188,10 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
179188
PathListMod { .. } => ()
180189
}
181190
}
182-
walk_path(visitor, path);
191+
192+
// Note that the `prefix` here is not a complete
193+
// path, so we don't use `visit_path`.
194+
walk_path(visitor, prefix);
183195
}
184196
}
185197
}
@@ -212,7 +224,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
212224
trait_ref: &'v PolyTraitRef)
213225
where V: Visitor<'v>
214226
{
215-
walk_lifetime_decls(visitor, &trait_ref.bound_lifetimes);
227+
walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
216228
visitor.visit_trait_ref(&trait_ref.trait_ref);
217229
}
218230

@@ -290,7 +302,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
290302
}
291303
ItemTrait(ref generics, _, ref bounds, ref methods) => {
292304
visitor.visit_generics(generics);
293-
walk_ty_param_bounds(visitor, bounds);
305+
walk_ty_param_bounds_helper(visitor, bounds);
294306
for method in methods.iter() {
295307
visitor.visit_trait_item(method)
296308
}
@@ -363,29 +375,29 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
363375
visitor.visit_ty(&*argument.ty)
364376
}
365377
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
366-
walk_ty_param_bounds(visitor, &function_declaration.bounds);
367-
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
378+
walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
379+
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
368380
}
369381
TyProc(ref function_declaration) => {
370382
for argument in function_declaration.decl.inputs.iter() {
371383
visitor.visit_ty(&*argument.ty)
372384
}
373385
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
374-
walk_ty_param_bounds(visitor, &function_declaration.bounds);
375-
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
386+
walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
387+
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
376388
}
377389
TyBareFn(ref function_declaration) => {
378390
for argument in function_declaration.decl.inputs.iter() {
379391
visitor.visit_ty(&*argument.ty)
380392
}
381393
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
382-
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
394+
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
383395
}
384396
TyPath(ref path, ref opt_bounds, id) => {
385397
visitor.visit_path(path, id);
386398
match *opt_bounds {
387399
Some(ref bounds) => {
388-
walk_ty_param_bounds(visitor, bounds);
400+
walk_ty_param_bounds_helper(visitor, bounds);
389401
}
390402
None => { }
391403
}
@@ -399,8 +411,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
399411
visitor.visit_ty(&**ty);
400412
visitor.visit_expr(&**expression)
401413
}
402-
TyPolyTraitRef(ref poly_trait_ref) => {
403-
visitor.visit_poly_trait_ref(&**poly_trait_ref)
414+
TyPolyTraitRef(ref bounds) => {
415+
walk_ty_param_bounds_helper(visitor, bounds)
404416
}
405417
TyTypeof(ref expression) => {
406418
visitor.visit_expr(&**expression)
@@ -409,33 +421,44 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
409421
}
410422
}
411423

412-
fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V,
413-
lifetimes: &'v Vec<LifetimeDef>) {
424+
pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
425+
lifetimes: &'v Vec<LifetimeDef>) {
414426
for l in lifetimes.iter() {
415427
visitor.visit_lifetime_decl(l);
416428
}
417429
}
418430

419431
pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
420432
for segment in path.segments.iter() {
421-
visitor.visit_ident(path.span, segment.identifier);
433+
visitor.visit_path_segment(path.span, segment);
434+
}
435+
}
422436

423-
match segment.parameters {
424-
ast::AngleBracketedParameters(ref data) => {
425-
for typ in data.types.iter() {
426-
visitor.visit_ty(&**typ);
427-
}
428-
for lifetime in data.lifetimes.iter() {
429-
visitor.visit_lifetime_ref(lifetime);
430-
}
437+
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
438+
path_span: Span,
439+
segment: &'v PathSegment) {
440+
visitor.visit_ident(path_span, segment.identifier);
441+
visitor.visit_path_parameters(path_span, &segment.parameters);
442+
}
443+
444+
pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
445+
_path_span: Span,
446+
path_parameters: &'v PathParameters) {
447+
match *path_parameters {
448+
ast::AngleBracketedParameters(ref data) => {
449+
for typ in data.types.iter() {
450+
visitor.visit_ty(&**typ);
431451
}
432-
ast::ParenthesizedParameters(ref data) => {
433-
for typ in data.inputs.iter() {
434-
visitor.visit_ty(&**typ);
435-
}
436-
for typ in data.output.iter() {
437-
visitor.visit_ty(&**typ);
438-
}
452+
for lifetime in data.lifetimes.iter() {
453+
visitor.visit_lifetime_ref(lifetime);
454+
}
455+
}
456+
ast::ParenthesizedParameters(ref data) => {
457+
for typ in data.inputs.iter() {
458+
visitor.visit_ty(&**typ);
459+
}
460+
for typ in data.output.iter() {
461+
visitor.visit_ty(&**typ);
439462
}
440463
}
441464
}
@@ -511,32 +534,37 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
511534
}
512535
}
513536

514-
pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
515-
bounds: &'v OwnedSlice<TyParamBound>) {
537+
pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
538+
bounds: &'v OwnedSlice<TyParamBound>) {
516539
for bound in bounds.iter() {
517-
match *bound {
518-
TraitTyParamBound(ref typ) => {
519-
visitor.visit_poly_trait_ref(typ)
520-
}
521-
RegionTyParamBound(ref lifetime) => {
522-
visitor.visit_lifetime_ref(lifetime);
523-
}
540+
visitor.visit_ty_param_bound(bound)
541+
}
542+
}
543+
544+
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
545+
bound: &'v TyParamBound) {
546+
match *bound {
547+
TraitTyParamBound(ref typ) => {
548+
visitor.visit_poly_trait_ref(typ);
549+
}
550+
RegionTyParamBound(ref lifetime) => {
551+
visitor.visit_lifetime_ref(lifetime);
524552
}
525553
}
526554
}
527555

528556
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
529557
for type_parameter in generics.ty_params.iter() {
530-
walk_ty_param_bounds(visitor, &type_parameter.bounds);
558+
walk_ty_param_bounds_helper(visitor, &type_parameter.bounds);
531559
match type_parameter.default {
532560
Some(ref ty) => visitor.visit_ty(&**ty),
533561
None => {}
534562
}
535563
}
536-
walk_lifetime_decls(visitor, &generics.lifetimes);
564+
walk_lifetime_decls_helper(visitor, &generics.lifetimes);
537565
for predicate in generics.where_clause.predicates.iter() {
538566
visitor.visit_ident(predicate.span, predicate.ident);
539-
walk_ty_param_bounds(visitor, &predicate.bounds);
567+
walk_ty_param_bounds_helper(visitor, &predicate.bounds);
540568
}
541569
}
542570

0 commit comments

Comments
 (0)