|
1 | 1 | use clippy_utils::diagnostics::span_lint_and_sugg;
|
2 |
| -use clippy_utils::source::snippet_opt; |
3 | 2 | use clippy_utils::ty::same_type_and_consts;
|
4 | 3 | use clippy_utils::{in_macro, meets_msrv, msrvs};
|
5 | 4 | use if_chain::if_chain;
|
6 | 5 | use rustc_errors::Applicability;
|
7 | 6 | use rustc_hir::{
|
8 | 7 | self as hir,
|
9 |
| - def::{self, DefKind}, |
| 8 | + def::{CtorOf, DefKind, Res}, |
10 | 9 | def_id::LocalDefId,
|
11 | 10 | intravisit::{walk_ty, NestedVisitorMap, Visitor},
|
12 |
| - Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment, |
13 |
| - QPath, TyKind, |
| 11 | + Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, QPath, TyKind, |
14 | 12 | };
|
15 | 13 | use rustc_lint::{LateContext, LateLintPass, LintContext};
|
16 | 14 | use rustc_middle::hir::map::Map;
|
17 | 15 | use rustc_middle::ty::{AssocKind, Ty};
|
18 | 16 | use rustc_semver::RustcVersion;
|
19 | 17 | use rustc_session::{declare_tool_lint, impl_lint_pass};
|
20 |
| -use rustc_span::{BytePos, Span}; |
| 18 | +use rustc_span::Span; |
21 | 19 | use rustc_typeck::hir_ty_to_ty;
|
22 | 20 |
|
23 | 21 | declare_clippy_lint! {
|
@@ -234,111 +232,58 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
234 | 232 | }
|
235 | 233 |
|
236 | 234 | fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
|
237 |
| - if in_macro(hir_ty.span) |
238 |
| - || in_impl(cx, hir_ty) |
239 |
| - || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) |
240 |
| - { |
241 |
| - return; |
242 |
| - } |
243 |
| - |
244 |
| - let lint_dependend_on_expr_kind = if let Some(StackItem::Check { |
245 |
| - hir_id, |
246 |
| - types_to_lint, |
247 |
| - types_to_skip, |
248 |
| - .. |
249 |
| - }) = self.stack.last() |
250 |
| - { |
251 |
| - if types_to_skip.contains(&hir_ty.hir_id) { |
252 |
| - false |
253 |
| - } else if types_to_lint.contains(&hir_ty.hir_id) { |
254 |
| - true |
255 |
| - } else { |
256 |
| - let self_ty = ty_from_hir_id(cx, *hir_id); |
257 |
| - should_lint_ty(hir_ty, hir_ty_to_ty(cx.tcx, hir_ty), self_ty) |
258 |
| - } |
259 |
| - } else { |
260 |
| - false |
261 |
| - }; |
262 |
| - |
263 |
| - if lint_dependend_on_expr_kind { |
264 |
| - // FIXME: this span manipulation should not be necessary |
265 |
| - // @flip1995 found an ast lowering issue in |
266 |
| - // https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162 |
| 235 | + if_chain! { |
| 236 | + if !in_macro(hir_ty.span) && !in_impl(cx, hir_ty); |
| 237 | + if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS); |
| 238 | + if let Some(StackItem::Check { |
| 239 | + hir_id, |
| 240 | + types_to_lint, |
| 241 | + types_to_skip, |
| 242 | + .. |
| 243 | + }) = self.stack.last(); |
| 244 | + if !types_to_skip.contains(&hir_ty.hir_id); |
| 245 | + if types_to_lint.contains(&hir_ty.hir_id) |
| 246 | + || { |
| 247 | + let self_ty = ty_from_hir_id(cx, *hir_id); |
| 248 | + should_lint_ty(hir_ty, hir_ty_to_ty(cx.tcx, hir_ty), self_ty) |
| 249 | + }; |
267 | 250 | let hir = cx.tcx.hir();
|
268 | 251 | let id = hir.get_parent_node(hir_ty.hir_id);
|
269 |
| - |
270 |
| - if !hir.opt_span(id).map_or(false, in_macro) { |
271 |
| - match hir.find(id) { |
272 |
| - Some(Node::Expr(Expr { |
273 |
| - kind: ExprKind::Path(QPath::TypeRelative(_, segment)), |
274 |
| - .. |
275 |
| - })) => span_lint_until_last_segment(cx, hir_ty.span, segment), |
276 |
| - _ => span_lint(cx, hir_ty.span), |
277 |
| - } |
| 252 | + if !hir.opt_span(id).map_or(false, in_macro); |
| 253 | + then { |
| 254 | + span_lint(cx, hir_ty.span); |
278 | 255 | }
|
279 | 256 | }
|
280 | 257 | }
|
281 | 258 |
|
282 | 259 | fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
283 |
| - fn expr_ty_matches(cx: &LateContext<'_>, expr: &Expr<'_>, self_ty: Ty<'_>) -> bool { |
284 |
| - let def_id = expr.hir_id.owner; |
285 |
| - if cx.tcx.has_typeck_results(def_id) { |
286 |
| - cx.tcx.typeck(def_id).expr_ty_opt(expr) == Some(self_ty) |
287 |
| - } else { |
288 |
| - false |
289 |
| - } |
290 |
| - } |
291 |
| - |
292 |
| - if in_macro(expr.span) || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) { |
293 |
| - return; |
| 260 | + if_chain! { |
| 261 | + if !in_macro(expr.span); |
| 262 | + if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS); |
| 263 | + if let Some(StackItem::Check { hir_id, .. }) = self.stack.last(); |
| 264 | + if cx.typeck_results().expr_ty(expr) == ty_from_hir_id(cx, *hir_id); |
| 265 | + then {} else { return; } |
294 | 266 | }
|
295 |
| - |
296 |
| - if let Some(StackItem::Check { hir_id, .. }) = self.stack.last() { |
297 |
| - let self_ty = ty_from_hir_id(cx, *hir_id); |
298 |
| - |
299 |
| - match &expr.kind { |
300 |
| - ExprKind::Struct(QPath::Resolved(_, path), ..) => { |
301 |
| - if expr_ty_matches(cx, expr, self_ty) { |
302 |
| - match path.res { |
303 |
| - def::Res::SelfTy(..) => (), |
304 |
| - def::Res::Def(DefKind::Variant, _) => span_lint_on_path_until_last_segment(cx, path), |
305 |
| - _ => { |
306 |
| - span_lint(cx, path.span); |
307 |
| - }, |
308 |
| - } |
309 |
| - } |
310 |
| - }, |
311 |
| - // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) |
312 |
| - ExprKind::Call(fun, _) => { |
313 |
| - if let Expr { |
314 |
| - kind: ExprKind::Path(ref qpath), |
315 |
| - .. |
316 |
| - } = fun |
317 |
| - { |
318 |
| - if expr_ty_matches(cx, expr, self_ty) { |
319 |
| - let res = cx.qpath_res(qpath, fun.hir_id); |
320 |
| - |
321 |
| - if let def::Res::Def(DefKind::Ctor(ctor_of, _), ..) = res { |
322 |
| - match ctor_of { |
323 |
| - def::CtorOf::Variant => { |
324 |
| - span_lint_on_qpath_resolved(cx, qpath, true); |
325 |
| - }, |
326 |
| - def::CtorOf::Struct => { |
327 |
| - span_lint_on_qpath_resolved(cx, qpath, false); |
328 |
| - }, |
329 |
| - } |
330 |
| - } |
| 267 | + match expr.kind { |
| 268 | + ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res { |
| 269 | + Res::SelfTy(..) => (), |
| 270 | + Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path), |
| 271 | + _ => span_lint(cx, path.span), |
| 272 | + }, |
| 273 | + // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) |
| 274 | + ExprKind::Call(fun, _) => { |
| 275 | + if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind { |
| 276 | + if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res { |
| 277 | + match ctor_of { |
| 278 | + CtorOf::Variant => lint_path_to_variant(cx, path), |
| 279 | + CtorOf::Struct => span_lint(cx, path.span), |
331 | 280 | }
|
332 | 281 | }
|
333 |
| - }, |
334 |
| - // unit enum variants (`Enum::A`) |
335 |
| - ExprKind::Path(qpath) => { |
336 |
| - if expr_ty_matches(cx, expr, self_ty) { |
337 |
| - span_lint_on_qpath_resolved(cx, qpath, true); |
338 |
| - } |
339 |
| - }, |
340 |
| - _ => (), |
341 |
| - } |
| 282 | + } |
| 283 | + }, |
| 284 | + // unit enum variants (`Enum::A`) |
| 285 | + ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path), |
| 286 | + _ => (), |
342 | 287 | }
|
343 | 288 | }
|
344 | 289 |
|
@@ -405,33 +350,12 @@ fn span_lint(cx: &LateContext<'_>, span: Span) {
|
405 | 350 | );
|
406 | 351 | }
|
407 | 352 |
|
408 |
| -#[allow(clippy::cast_possible_truncation)] |
409 |
| -fn span_lint_until_last_segment(cx: &LateContext<'_>, span: Span, segment: &PathSegment<'_>) { |
410 |
| - let sp = span.with_hi(segment.ident.span.lo()); |
411 |
| - // remove the trailing :: |
412 |
| - let span_without_last_segment = match snippet_opt(cx, sp) { |
413 |
| - Some(snippet) => match snippet.rfind("::") { |
414 |
| - Some(bidx) => sp.with_hi(sp.lo() + BytePos(bidx as u32)), |
415 |
| - None => sp, |
416 |
| - }, |
417 |
| - None => sp, |
418 |
| - }; |
419 |
| - span_lint(cx, span_without_last_segment); |
420 |
| -} |
421 |
| - |
422 |
| -fn span_lint_on_path_until_last_segment(cx: &LateContext<'_>, path: &Path<'_>) { |
423 |
| - if path.segments.len() > 1 { |
424 |
| - span_lint_until_last_segment(cx, path.span, path.segments.last().unwrap()); |
425 |
| - } |
426 |
| -} |
427 |
| - |
428 |
| -fn span_lint_on_qpath_resolved(cx: &LateContext<'_>, qpath: &QPath<'_>, until_last_segment: bool) { |
429 |
| - if let QPath::Resolved(_, path) = qpath { |
430 |
| - if until_last_segment { |
431 |
| - span_lint_on_path_until_last_segment(cx, path); |
432 |
| - } else { |
433 |
| - span_lint(cx, path.span); |
434 |
| - } |
| 353 | +fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) { |
| 354 | + if let [.., self_seg, _variant] = path.segments { |
| 355 | + let span = path |
| 356 | + .span |
| 357 | + .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi()); |
| 358 | + span_lint(cx, span); |
435 | 359 | }
|
436 | 360 | }
|
437 | 361 |
|
@@ -462,7 +386,7 @@ fn should_lint_ty(hir_ty: &hir::Ty<'_>, ty: Ty<'_>, self_ty: Ty<'_>) -> bool {
|
462 | 386 | if same_type_and_consts(ty, self_ty);
|
463 | 387 | if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
|
464 | 388 | then {
|
465 |
| - !matches!(path.res, def::Res::SelfTy(..)) |
| 389 | + !matches!(path.res, Res::SelfTy(..) | Res::Def(DefKind::TyParam, _)) |
466 | 390 | } else {
|
467 | 391 | false
|
468 | 392 | }
|
|
0 commit comments