summaryrefslogtreecommitdiffstats
path: root/src/test/incremental/change_add_field/struct_point.rs
blob: 3308ea56222f535ea45c64eaf971e59433fec6b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Test where we change a type definition by adding a field.  Fns with
// this type in their signature are recompiled, as are their callers.
// Fns with that type used only in their body are also recompiled, but
// their callers are not.

// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
// build-pass

#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![crate_type = "rlib"]

// These are expected to require codegen.
#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-fn_with_type_in_sig", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-call_fn_with_type_in_sig", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-fn_with_type_in_body", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-fn_make_struct", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-fn_read_field", cfg="cfail2")]
#![rustc_partition_codegened(module="struct_point-fn_write_field", cfg="cfail2")]

#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="cfail2")]

pub mod point {
    #[cfg(cfail1)]
    pub struct Point {
        pub x: f32,
        pub y: f32,
    }

    #[cfg(cfail2)]
    pub struct Point {
        pub x: f32,
        pub y: f32,
        pub z: f32,
    }

    impl Point {
        pub fn origin() -> Point {
            #[cfg(cfail1)]
            return Point { x: 0.0, y: 0.0 };

            #[cfg(cfail2)]
            return Point { x: 0.0, y: 0.0, z: 0.0 };
        }

        pub fn total(&self) -> f32 {
            #[cfg(cfail1)]
            return self.x + self.y;

            #[cfg(cfail2)]
            return self.x + self.y + self.z;
        }

        pub fn x(&self) -> f32 {
            self.x
        }
    }
}

/// A function that has the changed type in its signature; must currently be
/// rebuilt.
///
/// You could imagine that, in the future, if the change were
/// sufficiently "private", we might not need to type-check again.
/// Rebuilding is probably always necessary since the layout may be
/// affected.
pub mod fn_with_type_in_sig {
    use point::Point;

    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
    pub fn boop(p: Option<&Point>) -> f32 {
        p.map(|p| p.total()).unwrap_or(0.0)
    }
}

/// Call a function that has the changed type in its signature; this
/// currently must also be rebuilt.
///
/// You could imagine that, in the future, if the change were
/// sufficiently "private", we might not need to type-check again.
/// Rebuilding is probably always necessary since the layout may be
/// affected.
pub mod call_fn_with_type_in_sig {
    use fn_with_type_in_sig;

    #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
    pub fn bip() -> f32 {
        fn_with_type_in_sig::boop(None)
    }
}

/// A function that uses the changed type, but only in its body, not its
/// signature.
///
/// You could imagine that, in the future, if the change were
/// sufficiently "private", we might not need to type-check again.
/// Rebuilding is probably always necessary since the layout may be
/// affected.
pub mod fn_with_type_in_body {
    use point::Point;

    #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
    pub fn boop() -> f32 {
        Point::origin().total()
    }
}

/// A function `X` that calls a function `Y`, where `Y` uses the changed type in its
/// body. In this case, the effects of the change should be contained
/// to `Y`; `X` should not have to be rebuilt, nor should it need to be
/// type-checked again.
pub mod call_fn_with_type_in_body {
    use fn_with_type_in_body;

    #[rustc_clean(cfg="cfail2")]
    pub fn bip() -> f32 {
        fn_with_type_in_body::boop()
    }
}

/// A function item that makes an instance of `Point` but does not invoke methods.
pub mod fn_make_struct {
    use point::Point;

    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
    pub fn make_origin(p: Point) -> Point {
        Point { ..p }
    }
}

/// A function item that reads fields from `Point` but does not invoke methods.
pub mod fn_read_field {
    use point::Point;

    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
    pub fn get_x(p: Point) -> f32 {
        p.x
    }
}

/// A function item that writes to a field of `Point` but does not invoke methods.
pub mod fn_write_field {
    use point::Point;

    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
    pub fn inc_x(p: &mut Point) {
        p.x += 1.0;
    }
}