|
1 | 1 | use rustc::lint::*;
|
2 | 2 | use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
|
3 |
| -use rustc::ty; |
4 | 3 | use rustc::hir::*;
|
5 | 4 | use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then};
|
6 | 5 |
|
@@ -66,66 +65,76 @@ impl LateLintPass for Transmute {
|
66 | 65 | let from_ty = cx.tcx.expr_ty(&args[0]);
|
67 | 66 | let to_ty = cx.tcx.expr_ty(e);
|
68 | 67 |
|
69 |
| - if from_ty == to_ty { |
70 |
| - span_lint(cx, |
71 |
| - USELESS_TRANSMUTE, |
72 |
| - e.span, |
73 |
| - &format!("transmute from a type (`{}`) to itself", from_ty)); |
74 |
| - } else if is_ptr_to(to_ty, from_ty) { |
75 |
| - span_lint(cx, |
76 |
| - CROSSPOINTER_TRANSMUTE, |
77 |
| - e.span, |
78 |
| - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", |
79 |
| - from_ty, |
80 |
| - to_ty)); |
81 |
| - } else if is_ptr_to(from_ty, to_ty) { |
82 |
| - span_lint(cx, |
83 |
| - CROSSPOINTER_TRANSMUTE, |
84 |
| - e.span, |
85 |
| - &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", |
86 |
| - from_ty, |
87 |
| - to_ty)); |
88 |
| - } else { |
89 |
| - check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); |
90 |
| - } |
91 |
| - } |
92 |
| - } |
93 |
| - } |
94 |
| - } |
95 |
| -} |
| 68 | + match (&from_ty.sty, &to_ty.sty) { |
| 69 | + _ if from_ty == to_ty => span_lint( |
| 70 | + cx, |
| 71 | + USELESS_TRANSMUTE, |
| 72 | + e.span, |
| 73 | + &format!("transmute from a type (`{}`) to itself", from_ty), |
| 74 | + ), |
| 75 | + (&TyRef(_, rty), &TyRawPtr(ptr_ty)) => span_lint_and_then( |
| 76 | + cx, |
| 77 | + USELESS_TRANSMUTE, |
| 78 | + e.span, |
| 79 | + "transmute from a reference to a pointer", |
| 80 | + |db| { |
| 81 | + if let Some(arg) = snippet_opt(cx, args[0].span) { |
| 82 | + let sugg = if ptr_ty == rty { |
| 83 | + format!("{} as {}", arg, to_ty) |
| 84 | + } else { |
| 85 | + format!("{} as {} as {}", arg, cx.tcx.mk_ptr(rty), to_ty) |
| 86 | + }; |
96 | 87 |
|
97 |
| -fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool { |
98 |
| - if let TyRawPtr(from_ptr) = from.sty { |
99 |
| - from_ptr.ty == to |
100 |
| - } else { |
101 |
| - false |
102 |
| - } |
103 |
| -} |
| 88 | + db.span_suggestion(e.span, "try", sugg); |
| 89 | + } |
| 90 | + }, |
| 91 | + ), |
| 92 | + (&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( |
| 93 | + cx, |
| 94 | + CROSSPOINTER_TRANSMUTE, |
| 95 | + e.span, |
| 96 | + &format!("transmute from a type (`{}`) to the type that it points to (`{}`)", |
| 97 | + from_ty, |
| 98 | + to_ty), |
| 99 | + ), |
| 100 | + (_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( |
| 101 | + cx, |
| 102 | + CROSSPOINTER_TRANSMUTE, |
| 103 | + e.span, |
| 104 | + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", |
| 105 | + from_ty, |
| 106 | + to_ty), |
| 107 | + ), |
| 108 | + (&TyRawPtr(from_pty), &TyRef(_, to_rty)) => span_lint_and_then( |
| 109 | + cx, |
| 110 | + TRANSMUTE_PTR_TO_REF, |
| 111 | + e.span, |
| 112 | + &format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", |
| 113 | + from_ty, |
| 114 | + to_ty), |
| 115 | + |db| { |
| 116 | + if let Some(arg) = snippet_opt(cx, args[0].span) { |
| 117 | + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { |
| 118 | + ("&mut *", "*mut") |
| 119 | + } else { |
| 120 | + ("&*", "*const") |
| 121 | + }; |
104 | 122 |
|
105 |
| -fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) { |
106 |
| - if let TyRawPtr(ref from_pty) = from_ty.sty { |
107 |
| - if let TyRef(_, ref to_rty) = to_ty.sty { |
108 |
| - let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", |
109 |
| - from_ty, |
110 |
| - to_ty); |
111 |
| - span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| { |
112 |
| - if let Some(arg) = snippet_opt(cx, arg.span) { |
113 |
| - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { |
114 |
| - ("&mut *", "*mut") |
115 |
| - } else { |
116 |
| - ("&*", "*const") |
117 |
| - }; |
118 | 123 |
|
| 124 | + let sugg = if from_pty.ty == to_rty.ty { |
| 125 | + format!("{}{}", deref, arg) |
| 126 | + } else { |
| 127 | + format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) |
| 128 | + }; |
119 | 129 |
|
120 |
| - let sugg = if from_pty.ty == to_rty.ty { |
121 |
| - format!("{}{}", deref, arg) |
122 |
| - } else { |
123 |
| - format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) |
| 130 | + db.span_suggestion(e.span, "try", sugg); |
| 131 | + } |
| 132 | + }, |
| 133 | + ), |
| 134 | + _ => return, |
124 | 135 | };
|
125 |
| - |
126 |
| - db.span_suggestion(e.span, "try", sugg); |
127 | 136 | }
|
128 |
| - }); |
| 137 | + } |
129 | 138 | }
|
130 | 139 | }
|
131 | 140 | }
|
0 commit comments