Diff
Not logged in

Differences From Artifact [85395c99bf]:

To Artifact [8615a5a68a]:


4
5
6
7
8
9
10


11
12
13
14
15
16
17
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
...
238
239
240
241
242
243
244













245
246
247
248
249
250
251
...
353
354
355
356
357
358
359



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386




387
388
389
390
391
392
393
394
395
396
397
398



399

400
401
402
403
404
405
406
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
825
826
827
828
829
830
831





832
833
834
835
836
837
838
...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985

986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
....
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
....
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
....
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
....
1279
1280
1281
1282
1283
1284
1285


1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
....
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
....
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
//
// 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.



use graphviz::IntoCow;
use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
................................................................................
    }

    /// Returns an iterator over all temporaries.
    #[inline]
    pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
            if self.local_decls[local].source_info.is_none() {
                Some(local)
            } else {
                None
            }
        })
    }

    /// Returns an iterator over all user-declared locals.
    #[inline]
    pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
            if self.local_decls[local].source_info.is_none() {
                None
            } else {
                Some(local)
            }
        })
    }

    /// Returns an iterator over all function arguments.
    #[inline]
    pub fn args_iter(&self) -> impl Iterator<Item=Local> {
................................................................................
    /// invalidating statement indices in `Location`s.
    pub fn make_statement_nop(&mut self, location: Location) {
        let block = &mut self[location.block];
        debug_assert!(location.statement_index < block.statements.len());
        block.statements[location.statement_index].make_nop()
    }
}














impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
    type Output = BasicBlockData<'tcx>;

    #[inline]
    fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
        &self.basic_blocks()[index]
................................................................................
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct LocalDecl<'tcx> {
    /// `let mut x` vs `let x`.
    ///
    /// Temporaries and the return pointer are always mutable.
    pub mutability: Mutability,




    /// Type of this local.
    pub ty: Ty<'tcx>,

    /// Name of the local, used in debuginfo and pretty-printing.
    ///
    /// Note that function arguments can also have this set to `Some(_)`
    /// to generate better debuginfo.
    pub name: Option<Name>,

    /// For user-declared variables, stores their source information.
    ///
    /// For temporaries, this is `None`.
    ///
    /// This is the primary way to differentiate between user-declared
    /// variables and compiler-generated temporaries.
    pub source_info: Option<SourceInfo>,
}

impl<'tcx> LocalDecl<'tcx> {
    /// Create a new `LocalDecl` for a temporary.
    #[inline]
    pub fn new_temp(ty: Ty<'tcx>) -> Self {
        LocalDecl {
            mutability: Mutability::Mut,
            ty: ty,
            name: None,
            source_info: None,




        }
    }

    /// Builds a `LocalDecl` for the return pointer.
    ///
    /// This must be inserted into the `local_decls` list as the first local.
    #[inline]
    pub fn new_return_pointer(return_ty: Ty) -> LocalDecl {
        LocalDecl {
            mutability: Mutability::Mut,
            ty: return_ty,
            source_info: None,



            name: None,     // FIXME maybe we do want some name here?

        }
    }
}

/// A closure capture, with its name and mode.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct UpvarDecl {
................................................................................
    /// Start a live range for the storage of the local.
    StorageLive(Lvalue<'tcx>),

    /// End the current live range for the storage of the local.
    StorageDead(Lvalue<'tcx>),

    InlineAsm {
        asm: InlineAsm,
        outputs: Vec<Lvalue<'tcx>>,
        inputs: Vec<Operand<'tcx>>
    },

    /// No-op. Useful for deleting instructions without affecting statement indices.
    Nop,
}
................................................................................
/// The def-id of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
    pub def_id: DefId,
    pub ty: Ty<'tcx>,
}






/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Lvalue`. See the aliases
/// `LvalueProjection` etc below.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct Projection<'tcx, B, V> {
................................................................................

/// These are values that can appear inside an rvalue (or an index
/// lvalue). They are intentionally limited to prevent rvalues from
/// being nested in one another.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
    Consume(Lvalue<'tcx>),
    Constant(Constant<'tcx>),
}

impl<'tcx> Debug for Operand<'tcx> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        use self::Operand::*;
        match *self {
            Constant(ref a) => write!(fmt, "{:?}", a),
            Consume(ref lv) => write!(fmt, "{:?}", lv),
        }
    }
}

impl<'tcx> Operand<'tcx> {

    pub fn item<'a>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                    def_id: DefId,
                    substs: &'tcx Substs<'tcx>,
                    span: Span)
                    -> Self
    {
        Operand::Constant(Constant {
            span: span,
            ty: tcx.item_type(def_id).subst(tcx, substs),
            literal: Literal::Item { def_id, substs }
        })
    }

}

///////////////////////////////////////////////////////////////////////////
/// Rvalues
................................................................................
    /// x (either a move or copy, depending on type of x)
    Use(Operand<'tcx>),

    /// [x; 32]
    Repeat(Operand<'tcx>, ConstUsize),

    /// &x or &mut x
    Ref(&'tcx Region, BorrowKind, Lvalue<'tcx>),

    /// length of a [X] or [X;n] value
    Len(Lvalue<'tcx>),

    Cast(CastKind, Operand<'tcx>, Ty<'tcx>),

    BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
................................................................................
    Box(Ty<'tcx>),

    /// Create an aggregate value, like a tuple or struct.  This is
    /// only needed because we want to distinguish `dest = Foo { x:
    /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
    /// that `Foo` has a destructor. These rvalues can be optimized
    /// away after type-checking and before lowering.
    Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CastKind {
    Misc,

    /// Convert unique, zero-sized type for a fn to fn()
................................................................................
                    let mut tuple_fmt = fmt.debug_tuple("");
                    for lv in lvs {
                        tuple_fmt.field(lv);
                    }
                    tuple_fmt.finish()
                }

                match *kind {
                    AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),

                    AggregateKind::Tuple => {
                        match lvs.len() {
                            0 => write!(fmt, "()"),
                            1 => write!(fmt, "({:?},)", lvs[0]),
                            _ => fmt_tuple(fmt, lvs),
................................................................................
            let escaped: String = bytes
                .iter()
                .flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
                .collect();
            write!(fmt, "b\"{}\"", escaped)
        }
        Bool(b) => write!(fmt, "{:?}", b),


        Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
        Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
            bug!("ConstVal `{:?}` should not be in MIR", const_val),
        Char(c) => write!(fmt, "{:?}", c),
    }
}

fn item_path_str(def_id: DefId) -> String {
    ty::tls::with(|tcx| tcx.item_path_str(def_id))
}

................................................................................
                BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            CheckedBinaryOp(op, ref rhs, ref lhs) =>
                CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
            Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
            Box(ty) => Box(ty.fold_with(folder)),
            Aggregate(ref kind, ref fields) => {
                let kind = match *kind {
                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                    AggregateKind::Tuple => AggregateKind::Tuple,
                    AggregateKind::Adt(def, v, substs, n) =>
                        AggregateKind::Adt(def, v, substs.fold_with(folder), n),
                    AggregateKind::Closure(id, substs) =>
                        AggregateKind::Closure(id, substs.fold_with(folder))
                };
................................................................................
            BinaryOp(_, ref rhs, ref lhs) |
            CheckedBinaryOp(_, ref rhs, ref lhs) =>
                rhs.visit_with(visitor) || lhs.visit_with(visitor),
            UnaryOp(_, ref val) => val.visit_with(visitor),
            Discriminant(ref lval) => lval.visit_with(visitor),
            Box(ty) => ty.visit_with(visitor),
            Aggregate(ref kind, ref fields) => {
                (match *kind {
                    AggregateKind::Array(ty) => ty.visit_with(visitor),
                    AggregateKind::Tuple => false,
                    AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
                    AggregateKind::Closure(_, substs) => substs.visit_with(visitor)
                }) || fields.visit_with(visitor)
            }
        }







>
>







 







|
|

|









|
|

|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>









|
<
<
<
<
<
|





|




|
>
>
>
>







|



|
>
>
>

>







 







|







 







>
>
>
>
>







 







|













>
|
|
|
|
|
<
|

|
|







 







|







 







|







 







|







 







>
>



<







 







|







 







|







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387





388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
...
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
....
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
....
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
....
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
....
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316

1317
1318
1319
1320
1321
1322
1323
....
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
....
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
//
// 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.

//! MIR datatypes and passes. See [the README](README.md) for details.

use graphviz::IntoCow;
use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
................................................................................
    }

    /// Returns an iterator over all temporaries.
    #[inline]
    pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
            if self.local_decls[local].is_user_variable {
                None
            } else {
                Some(local)
            }
        })
    }

    /// Returns an iterator over all user-declared locals.
    #[inline]
    pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
            let local = Local::new(index);
            if self.local_decls[local].is_user_variable {
                Some(local)
            } else {
                None
            }
        })
    }

    /// Returns an iterator over all function arguments.
    #[inline]
    pub fn args_iter(&self) -> impl Iterator<Item=Local> {
................................................................................
    /// invalidating statement indices in `Location`s.
    pub fn make_statement_nop(&mut self, location: Location) {
        let block = &mut self[location.block];
        debug_assert!(location.statement_index < block.statements.len());
        block.statements[location.statement_index].make_nop()
    }
}

impl_stable_hash_for!(struct Mir<'tcx> {
    basic_blocks,
    visibility_scopes,
    promoted,
    return_ty,
    local_decls,
    arg_count,
    upvar_decls,
    spread_arg,
    span,
    cache
});

impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
    type Output = BasicBlockData<'tcx>;

    #[inline]
    fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
        &self.basic_blocks()[index]
................................................................................
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct LocalDecl<'tcx> {
    /// `let mut x` vs `let x`.
    ///
    /// Temporaries and the return pointer are always mutable.
    pub mutability: Mutability,

    /// True if this corresponds to a user-declared local variable.
    pub is_user_variable: bool,

    /// Type of this local.
    pub ty: Ty<'tcx>,

    /// Name of the local, used in debuginfo and pretty-printing.
    ///
    /// Note that function arguments can also have this set to `Some(_)`
    /// to generate better debuginfo.
    pub name: Option<Name>,

    /// Source info of the local.





    pub source_info: SourceInfo,
}

impl<'tcx> LocalDecl<'tcx> {
    /// Create a new `LocalDecl` for a temporary.
    #[inline]
    pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
        LocalDecl {
            mutability: Mutability::Mut,
            ty: ty,
            name: None,
            source_info: SourceInfo {
                span: span,
                scope: ARGUMENT_VISIBILITY_SCOPE
            },
            is_user_variable: false
        }
    }

    /// Builds a `LocalDecl` for the return pointer.
    ///
    /// This must be inserted into the `local_decls` list as the first local.
    #[inline]
    pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl {
        LocalDecl {
            mutability: Mutability::Mut,
            ty: return_ty,
            source_info: SourceInfo {
                span: span,
                scope: ARGUMENT_VISIBILITY_SCOPE
            },
            name: None,     // FIXME maybe we do want some name here?
            is_user_variable: false
        }
    }
}

/// A closure capture, with its name and mode.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct UpvarDecl {
................................................................................
    /// Start a live range for the storage of the local.
    StorageLive(Lvalue<'tcx>),

    /// End the current live range for the storage of the local.
    StorageDead(Lvalue<'tcx>),

    InlineAsm {
        asm: Box<InlineAsm>,
        outputs: Vec<Lvalue<'tcx>>,
        inputs: Vec<Operand<'tcx>>
    },

    /// No-op. Useful for deleting instructions without affecting statement indices.
    Nop,
}
................................................................................
/// The def-id of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
    pub def_id: DefId,
    pub ty: Ty<'tcx>,
}

impl_stable_hash_for!(struct Static<'tcx> {
    def_id,
    ty
});

/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Lvalue`. See the aliases
/// `LvalueProjection` etc below.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct Projection<'tcx, B, V> {
................................................................................

/// These are values that can appear inside an rvalue (or an index
/// lvalue). They are intentionally limited to prevent rvalues from
/// being nested in one another.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
    Consume(Lvalue<'tcx>),
    Constant(Box<Constant<'tcx>>),
}

impl<'tcx> Debug for Operand<'tcx> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        use self::Operand::*;
        match *self {
            Constant(ref a) => write!(fmt, "{:?}", a),
            Consume(ref lv) => write!(fmt, "{:?}", lv),
        }
    }
}

impl<'tcx> Operand<'tcx> {
    pub fn function_handle<'a>(
        tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
        def_id: DefId,
        substs: &'tcx Substs<'tcx>,
        span: Span,
    ) -> Self {

        Operand::Constant(box Constant {
            span: span,
            ty: tcx.type_of(def_id).subst(tcx, substs),
            literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
        })
    }

}

///////////////////////////////////////////////////////////////////////////
/// Rvalues
................................................................................
    /// x (either a move or copy, depending on type of x)
    Use(Operand<'tcx>),

    /// [x; 32]
    Repeat(Operand<'tcx>, ConstUsize),

    /// &x or &mut x
    Ref(Region<'tcx>, BorrowKind, Lvalue<'tcx>),

    /// length of a [X] or [X;n] value
    Len(Lvalue<'tcx>),

    Cast(CastKind, Operand<'tcx>, Ty<'tcx>),

    BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
................................................................................
    Box(Ty<'tcx>),

    /// Create an aggregate value, like a tuple or struct.  This is
    /// only needed because we want to distinguish `dest = Foo { x:
    /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
    /// that `Foo` has a destructor. These rvalues can be optimized
    /// away after type-checking and before lowering.
    Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CastKind {
    Misc,

    /// Convert unique, zero-sized type for a fn to fn()
................................................................................
                    let mut tuple_fmt = fmt.debug_tuple("");
                    for lv in lvs {
                        tuple_fmt.field(lv);
                    }
                    tuple_fmt.finish()
                }

                match **kind {
                    AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),

                    AggregateKind::Tuple => {
                        match lvs.len() {
                            0 => write!(fmt, "()"),
                            1 => write!(fmt, "({:?},)", lvs[0]),
                            _ => fmt_tuple(fmt, lvs),
................................................................................
            let escaped: String = bytes
                .iter()
                .flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
                .collect();
            write!(fmt, "b\"{}\"", escaped)
        }
        Bool(b) => write!(fmt, "{:?}", b),
        Char(c) => write!(fmt, "{:?}", c),
        Variant(def_id) |
        Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
        Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
            bug!("ConstVal `{:?}` should not be in MIR", const_val),

    }
}

fn item_path_str(def_id: DefId) -> String {
    ty::tls::with(|tcx| tcx.item_path_str(def_id))
}

................................................................................
                BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            CheckedBinaryOp(op, ref rhs, ref lhs) =>
                CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
            UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
            Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
            Box(ty) => Box(ty.fold_with(folder)),
            Aggregate(ref kind, ref fields) => {
                let kind = box match **kind {
                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                    AggregateKind::Tuple => AggregateKind::Tuple,
                    AggregateKind::Adt(def, v, substs, n) =>
                        AggregateKind::Adt(def, v, substs.fold_with(folder), n),
                    AggregateKind::Closure(id, substs) =>
                        AggregateKind::Closure(id, substs.fold_with(folder))
                };
................................................................................
            BinaryOp(_, ref rhs, ref lhs) |
            CheckedBinaryOp(_, ref rhs, ref lhs) =>
                rhs.visit_with(visitor) || lhs.visit_with(visitor),
            UnaryOp(_, ref val) => val.visit_with(visitor),
            Discriminant(ref lval) => lval.visit_with(visitor),
            Box(ty) => ty.visit_with(visitor),
            Aggregate(ref kind, ref fields) => {
                (match **kind {
                    AggregateKind::Array(ty) => ty.visit_with(visitor),
                    AggregateKind::Tuple => false,
                    AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
                    AggregateKind::Closure(_, substs) => substs.visit_with(visitor)
                }) || fields.visit_with(visitor)
            }
        }