@@ -2087,6 +2087,82 @@ impl LintPass for InvalidNoMangleItems {
2087
2087
}
2088
2088
}
2089
2089
2090
+ #[ derive( Clone , Copy ) ]
2091
+ pub struct MutableTransmutes ;
2092
+
2093
+ declare_lint ! {
2094
+ MUTABLE_TRANSMUTES ,
2095
+ Deny ,
2096
+ "transmuting from &T to &mut T is undefined behavior"
2097
+ }
2098
+
2099
+ impl LintPass for MutableTransmutes {
2100
+ fn get_lints ( & self ) -> LintArray {
2101
+ lint_array ! ( MUTABLE_TRANSMUTES )
2102
+ }
2103
+
2104
+ fn check_expr ( & mut self , cx : & Context , expr : & ast:: Expr ) {
2105
+ use syntax:: ast:: DefId ;
2106
+ use syntax:: abi:: RustIntrinsic ;
2107
+ let msg = "transmuting from immutable to mutable is undefined behavior" ;
2108
+ match get_transmute_from_to ( cx, expr) {
2109
+ Some ( ( & ty:: ty_rptr( _, from_mt) , & ty:: ty_rptr( _, to_mt) ) ) => {
2110
+ if to_mt. mutbl == ast:: Mutability :: MutMutable
2111
+ && from_mt. mutbl == ast:: Mutability :: MutImmutable {
2112
+ cx. span_lint ( MUTABLE_TRANSMUTES , expr. span , msg) ;
2113
+ }
2114
+ }
2115
+ _ => ( )
2116
+ }
2117
+
2118
+ fn get_transmute_from_to < ' a , ' tcx > ( cx : & Context < ' a , ' tcx > , expr : & ast:: Expr )
2119
+ -> Option < ( & ' tcx ty:: sty < ' tcx > , & ' tcx ty:: sty < ' tcx > ) > {
2120
+ if let ast:: ExprPath ( ..) = expr. node {
2121
+ if let DefFn ( did, _) = ty:: resolve_expr ( cx. tcx , expr) {
2122
+ if def_id_is_transmute ( cx, did) {
2123
+ let typ = ty:: node_id_to_type ( cx. tcx , expr. id ) ;
2124
+ match typ. sty {
2125
+ ty:: ty_bare_fn( _, ref bare_fn) if bare_fn. abi == RustIntrinsic => {
2126
+ if let ty:: FnConverging ( to) = bare_fn. sig . 0 . output {
2127
+ let from = bare_fn. sig . 0 . inputs [ 0 ] ;
2128
+ return Some ( ( & from. sty , & to. sty ) ) ;
2129
+ }
2130
+ } ,
2131
+ _ => ( )
2132
+ }
2133
+ }
2134
+ }
2135
+ }
2136
+ None
2137
+ }
2138
+
2139
+ fn def_id_is_transmute ( cx : & Context , def_id : DefId ) -> bool {
2140
+ use syntax:: ast_map:: NodeForeignItem ;
2141
+ let intrinsic = match ty:: lookup_item_type ( cx. tcx , def_id) . ty . sty {
2142
+ ty:: ty_bare_fn( _, ref bfty) => bfty. abi == RustIntrinsic ,
2143
+ _ => return false
2144
+ } ;
2145
+ if def_id. krate == ast:: LOCAL_CRATE {
2146
+ match cx. tcx . map . get ( def_id. node ) {
2147
+ NodeForeignItem ( ref item) if intrinsic => {
2148
+ token:: get_ident ( item. ident ) ==
2149
+ token:: intern_and_get_ident ( "transmute" )
2150
+ }
2151
+ _ => false ,
2152
+ }
2153
+ } else {
2154
+ match csearch:: get_item_path ( cx. tcx , def_id) . last ( ) {
2155
+ Some ( ref last) if intrinsic => {
2156
+ token:: get_name ( last. name ( ) ) ==
2157
+ token:: intern_and_get_ident ( "transmute" )
2158
+ }
2159
+ _ => false ,
2160
+ }
2161
+ }
2162
+ }
2163
+ }
2164
+ }
2165
+
2090
2166
/// Forbids using the `#[feature(...)]` attribute
2091
2167
#[ derive( Copy , Clone ) ]
2092
2168
pub struct UnstableFeatures ;
0 commit comments