1
1
#[ doc = "
2
2
3
- Conversion from AST representation of types to the ty.rs representation.
4
-
5
- The main routine here is `ast_ty_to_ty()`: each use is parameterized
6
- by an instance of `ast_conv` and a `region_scope`.
7
-
8
- The `ast_conv` interface is the conversion context. It has two
9
- implementations, one for the crate context and one for the function
10
- context. The main purpose is to provide the `get_item_ty()` hook
11
- which looks up the type of an item by its def-id. This can be done in
12
- two ways: in the initial phase, when a crate context is provided, this
13
- will potentially trigger a call to `ty_of_item()`. Later, when a
14
- function context is used, this will simply be a lookup.
3
+ Conversion from AST representation of types to the ty.rs
4
+ representation. The main routine here is `ast_ty_to_ty()`: each use
5
+ is parameterized by an instance of `ast_conv` and a `region_scope`.
6
+
7
+ The parameterization of `ast_ty_to_ty()` is because it behaves
8
+ somewhat differently during the collect and check phases, particularly
9
+ with respect to looking up the types of top-level items. In the
10
+ collect phase, the crate context is used as the `ast_conv` instance;
11
+ in this phase, the `get_item_ty()` function triggers a recursive call
12
+ to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive
13
+ types and report an error). In the check phase, when the @fn_ctxt is
14
+ used as the `ast_conv`, `get_item_ty()` just looks up the item type in
15
+ `tcx.tcache`.
15
16
16
17
The `region_scope` interface controls how region references are
17
18
handled. It has two methods which are used to resolve anonymous
@@ -21,8 +22,30 @@ commonly you want either `empty_rscope`, which permits only the static
21
22
region, or `type_rscope`, which permits the self region if the type in
22
23
question is parameterized by a region.
23
24
25
+ Unlike the `ast_conv` iface, the region scope can change as we descend
26
+ the type. This is to accommodate the fact that (a) fn types are binding
27
+ scopes and (b) the default region may change. To understand case (a),
28
+ consider something like:
29
+
30
+ type foo = { x: &a.int, y: fn(&a.int) }
31
+
32
+ The type of `x` is an error because there is no region `a` in scope.
33
+ In the type of `y`, however, region `a` is considered a bound region
34
+ as it does not already appear in scope.
35
+
36
+ Case (b) says that if you have a type:
37
+ type foo/& = ...;
38
+ type bar = fn(&foo, &a.foo)
39
+ The fully expanded version of type bar is:
40
+ type bar = fn(&foo/&, &a.foo/&a)
41
+ Note that the self region for the `foo` defaulted to `&` in the first
42
+ case but `&a` in the second. Basically, defaults that appear inside
43
+ an rptr (`&r.T`) use the region `r` that appears in the rptr.
44
+
24
45
" ] ;
25
46
47
+ import check:: fn_ctxt;
48
+
26
49
iface ast_conv {
27
50
fn tcx( ) -> ty:: ctxt;
28
51
fn ccx ( ) -> @crate_ctxt ;
@@ -32,48 +55,6 @@ iface ast_conv {
32
55
fn ty_infer ( span : span ) -> ty:: t ;
33
56
}
34
57
35
- impl of ast_conv for @crate_ctxt {
36
- fn tcx ( ) -> ty:: ctxt { self . tcx }
37
- fn ccx ( ) -> @crate_ctxt { self }
38
-
39
- fn get_item_ty ( id : ast:: def_id ) -> ty:: ty_param_bounds_and_ty {
40
- if id. crate != ast:: local_crate {
41
- csearch:: get_type ( self . tcx , id)
42
- } else {
43
- alt self . tcx . items . find ( id. node ) {
44
- some ( ast_map:: node_item ( item, _) ) {
45
- ty_of_item ( self , item)
46
- }
47
- some ( ast_map:: node_native_item ( native_item, _, _) ) {
48
- ty_of_native_item ( self , native_item)
49
- }
50
- x {
51
- self. tcx . sess . bug ( #fmt[ "unexpected sort of item \
52
- in get_item_ty(): %?", x] ) ;
53
- }
54
- }
55
- }
56
- }
57
-
58
- fn ty_infer ( span : span ) -> ty:: t {
59
- self . tcx . sess . span_bug ( span,
60
- "found `ty_infer` in unexpected place" ) ;
61
- }
62
- }
63
-
64
- impl of ast_conv for @fn_ctxt {
65
- fn tcx ( ) -> ty:: ctxt { self . ccx . tcx }
66
- fn ccx ( ) -> @crate_ctxt { self . ccx }
67
-
68
- fn get_item_ty ( id : ast:: def_id ) -> ty:: ty_param_bounds_and_ty {
69
- ty:: lookup_item_type ( self . tcx ( ) , id)
70
- }
71
-
72
- fn ty_infer ( _span : span ) -> ty:: t {
73
- self . next_ty_var ( )
74
- }
75
- }
76
-
77
58
iface region_scope {
78
59
fn anon_region( ) -> result<ty:: region, str >;
79
60
fn named_region ( id : str ) -> result < ty:: region , str > ;
@@ -112,23 +93,6 @@ impl of region_scope for type_rscope {
112
93
}
113
94
}
114
95
115
- impl of region_scope for @fn_ctxt {
116
- fn anon_region ( ) -> result < ty:: region , str > {
117
- result:: ok ( self . next_region_var ( ) )
118
- }
119
- fn named_region ( id : str ) -> result < ty:: region , str > {
120
- empty_rscope. named_region ( id) . chain_err { |_e|
121
- alt self . in_scope_regions . find ( ty:: br_named ( id) ) {
122
- some ( r) { result:: ok ( r) }
123
- none if id == "blk" { self . block_region ( ) }
124
- none {
125
- result : : err ( #fmt[ "named region `%s` not in scope here" , id] )
126
- }
127
- }
128
- }
129
- }
130
- }
131
-
132
96
enum anon_rscope = { anon: ty:: region, base: region_scope} ;
133
97
fn in_anon_rscope < RS : region_scope copy> ( self : RS , r : ty:: region )
134
98
-> @anon_rscope {
@@ -159,6 +123,19 @@ impl of region_scope for @binding_rscope {
159
123
}
160
124
}
161
125
126
+ fn get_region_reporting_err ( tcx : ty:: ctxt ,
127
+ span : span ,
128
+ res : result < ty:: region , str > ) -> ty:: region {
129
+
130
+ alt res {
131
+ result : : ok ( r) { r }
132
+ result:: err ( e) {
133
+ tcx. sess . span_err ( span, e) ;
134
+ ty:: re_static
135
+ }
136
+ }
137
+ }
138
+
162
139
fn ast_region_to_region < AC : ast_conv , RS : region_scope > (
163
140
self : AC , rscope : RS , span : span , a_r : @ast:: region ) -> ty:: region {
164
141
@@ -233,36 +210,6 @@ fn ast_path_to_ty<AC: ast_conv, RS: region_scope copy>(
233
210
ret { substs : substs, ty : ty} ;
234
211
}
235
212
236
- /*
237
- Instantiates the path for the given iface reference, assuming that
238
- it's bound to a valid iface type. Returns the def_id for the defining
239
- iface. Fails if the type is a type other than an iface type.
240
- */
241
- fn instantiate_iface_ref ( ccx : @crate_ctxt , t : @ast:: iface_ref ,
242
- rp : ast:: region_param )
243
- -> ( ast:: def_id , ty_param_substs_and_ty ) {
244
-
245
- let sp = t. path . span , err = "can only implement interface types" ,
246
- sess = ccx. tcx . sess ;
247
-
248
- let rscope = type_rscope ( rp) ;
249
-
250
- alt lookup_def_tcx ( ccx. tcx , t. path . span , t. id ) {
251
- ast:: def_ty ( t_id) {
252
- let tpt = ast_path_to_ty ( ccx, rscope, t_id, t. path , t. id ) ;
253
- alt ty:: get ( tpt. ty ) . struct {
254
- ty:: ty_iface ( * ) {
255
- ( t_id, tpt)
256
- }
257
- _ { sess. span_fatal ( sp, err) ; }
258
- }
259
- }
260
- _ {
261
- sess. span_fatal ( sp, err) ;
262
- }
263
- }
264
- }
265
-
266
213
const NO_REGIONS : uint = 1 u;
267
214
const NO_TPS : uint = 2 u;
268
215
@@ -474,103 +421,6 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
474
421
ret typ;
475
422
}
476
423
477
- fn ty_of_item( ccx: @crate_ctxt, it: @ast:: item)
478
- -> ty:: ty_param_bounds_and_ty {
479
-
480
- let def_id = local_def( it. id) ;
481
- let tcx = ccx. tcx;
482
- alt tcx. tcache. find( def_id) {
483
- some( tpt) { ret tpt; }
484
- _ { }
485
- }
486
- alt it. node {
487
- ast : : item_const( t, _) {
488
- let typ = ccx. to_ty( empty_rscope, t) ;
489
- let tpt = no_params( typ) ;
490
- tcx. tcache. insert( local_def( it. id) , tpt) ;
491
- ret tpt;
492
- }
493
- ast:: item_fn( decl, tps, _) {
494
- let bounds = ty_param_bounds( ccx, tps) ;
495
- let tofd = ty_of_fn_decl( ccx, empty_rscope, ast:: proto_bare,
496
- decl, none) ;
497
- let tpt = { bounds: bounds,
498
- rp: ast:: rp_none, // functions do not have a self
499
- ty: ty:: mk_fn( ccx. tcx, tofd) } ;
500
- ccx. tcx. tcache. insert( local_def( it. id) , tpt) ;
501
- ret tpt;
502
- }
503
- ast:: item_ty( t, tps, rp) {
504
- alt tcx. tcache. find( local_def( it. id) ) {
505
- some( tpt) { ret tpt; }
506
- none { }
507
- }
508
-
509
- let tpt = {
510
- let ty = {
511
- let t0 = ccx. to_ty( type_rscope( rp) , t) ;
512
- // Do not associate a def id with a named, parameterized type
513
- // like "foo<X>". This is because otherwise ty_to_str will
514
- // print the name as merely "foo", as it has no way to
515
- // reconstruct the value of X.
516
- if !vec:: is_empty( tps) { t0 } else {
517
- ty:: mk_with_id( tcx, t0, def_id)
518
- }
519
- } ;
520
- { bounds: ty_param_bounds( ccx, tps) , rp: rp, ty: ty}
521
- } ;
522
-
523
- check_bounds_are_used( ccx, t. span, tps, rp, tpt. ty) ;
524
-
525
- tcx. tcache. insert( local_def( it. id) , tpt) ;
526
- ret tpt;
527
- }
528
- ast:: item_res( decl, tps, _, _, _, rp) {
529
- let { bounds, substs} = mk_substs( ccx, tps, rp) ;
530
- let t_arg = ty_of_arg( ccx, type_rscope( rp) ,
531
- decl. inputs[ 0 ] , none) ;
532
- let t = ty:: mk_res( tcx, local_def( it. id) , t_arg. ty, substs) ;
533
- let t_res = { bounds: bounds, rp: rp, ty: t} ;
534
- tcx. tcache. insert( local_def( it. id) , t_res) ;
535
- ret t_res;
536
- }
537
- ast:: item_enum( _, tps, rp) {
538
- // Create a new generic polytype.
539
- let { bounds, substs} = mk_substs( ccx, tps, rp) ;
540
- let t = ty:: mk_enum( tcx, local_def( it. id) , substs) ;
541
- let tpt = { bounds: bounds, rp: rp, ty: t} ;
542
- tcx. tcache. insert( local_def( it. id) , tpt) ;
543
- ret tpt;
544
- }
545
- ast:: item_iface( tps, rp, ms) {
546
- let { bounds, substs} = mk_substs( ccx, tps, rp) ;
547
- let t = ty:: mk_iface( tcx, local_def( it. id) , substs) ;
548
- let tpt = { bounds: bounds, rp: rp, ty: t} ;
549
- tcx. tcache. insert( local_def( it. id) , tpt) ;
550
- ret tpt;
551
- }
552
- ast:: item_class( tps, _, _, _, _, rp) {
553
- let { bounds, substs} = mk_substs( ccx, tps, rp) ;
554
- let t = ty:: mk_class( tcx, local_def( it. id) , substs) ;
555
- let tpt = { bounds: bounds, rp: rp, ty: t} ;
556
- tcx. tcache. insert( local_def( it. id) , tpt) ;
557
- ret tpt;
558
- }
559
- ast:: item_impl( * ) | ast:: item_mod( _) |
560
- ast:: item_native_mod( _) { fail; }
561
- }
562
- }
563
-
564
- fn ty_of_native_item( ccx: @crate_ctxt, it: @ast:: native_item)
565
- -> ty:: ty_param_bounds_and_ty {
566
- alt it. node {
567
- ast : : native_item_fn( fn_decl, params) {
568
- ret ty_of_native_fn_decl( ccx, fn_decl, params,
569
- local_def( it. id) ) ;
570
- }
571
- }
572
- }
573
-
574
424
fn ty_of_arg < AC : ast_conv , RS : region_scope copy> (
575
425
self : AC , rscope: RS , a: ast:: arg,
576
426
expected_ty: option < ty:: arg > ) -> ty:: arg {
@@ -651,61 +501,3 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy>(
651
501
}
652
502
653
503
654
- fn ty_param_bounds ( ccx : @crate_ctxt ,
655
- params : [ ast:: ty_param ] ) -> @[ ty:: param_bounds ] {
656
-
657
- fn compute_bounds ( ccx : @crate_ctxt ,
658
- param : ast:: ty_param ) -> ty:: param_bounds {
659
- @vec:: flat_map ( * param. bounds ) { |b|
660
- alt b {
661
- ast : : bound_send { [ ty:: bound_send] }
662
- ast:: bound_copy { [ ty:: bound_copy] }
663
- ast:: bound_iface ( t) {
664
- let ity = ast_ty_to_ty ( ccx, empty_rscope, t) ;
665
- alt ty:: get ( ity) . struct {
666
- ty:: ty_iface ( * ) {
667
- [ ty:: bound_iface ( ity) ]
668
- }
669
- _ {
670
- ccx. tcx . sess . span_err (
671
- t. span , "type parameter bounds must be \
672
- interface types") ;
673
- [ ]
674
- }
675
- }
676
- }
677
- }
678
- }
679
- }
680
-
681
- @params. map { |param|
682
- alt ccx. tcx. ty_param_bounds. find( param. id) {
683
- some( bs) { bs }
684
- none {
685
- let bounds = compute_bounds ( ccx, param) ;
686
- ccx. tcx . ty_param_bounds . insert ( param. id , bounds) ;
687
- bounds
688
- }
689
- }
690
- }
691
- }
692
-
693
- fn ty_of_native_fn_decl ( ccx : @crate_ctxt ,
694
- decl : ast:: fn_decl ,
695
- ty_params : [ ast:: ty_param ] ,
696
- def_id : ast:: def_id ) -> ty:: ty_param_bounds_and_ty {
697
-
698
- let bounds = ty_param_bounds ( ccx, ty_params) ;
699
- let rb = in_binding_rscope ( empty_rscope) ;
700
- let input_tys = decl. inputs . map { |a| ty_of_arg ( ccx, rb, a, none) } ;
701
- let output_ty = ast_ty_to_ty ( ccx, rb, decl. output ) ;
702
-
703
- let t_fn = ty:: mk_fn ( ccx. tcx , { proto: ast:: proto_bare,
704
- inputs: input_tys,
705
- output: output_ty,
706
- ret_style: ast:: return_val,
707
- constraints: [ ] } ) ;
708
- let tpt = { bounds: bounds, rp: ast:: rp_none, ty: t_fn} ;
709
- ccx. tcx . tcache . insert ( def_id, tpt) ;
710
- ret tpt;
711
- }
0 commit comments