|
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