diff options
| author | Lukas Markeffsky <@> | 2022-12-25 22:16:04 +0100 |
|---|---|---|
| committer | Lukas Markeffsky <@> | 2022-12-26 16:35:21 +0100 |
| commit | 1eba6c404fa3e64607fc3826214bd61ae10fa5bb (patch) | |
| tree | 939b08823ed2fc38a4f1deb7e488cb251247b808 /compiler/rustc_lint/src | |
| parent | 83e653920d694a010fad8c7d87d302c2d5b3a177 (diff) | |
| download | rust-1eba6c404fa3e64607fc3826214bd61ae10fa5bb.tar.gz rust-1eba6c404fa3e64607fc3826214bd61ae10fa5bb.zip | |
address review comments + better tests
Diffstat (limited to 'compiler/rustc_lint/src')
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 114 |
1 files changed, 63 insertions, 51 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3fc86545ed4..cdb901b7f86 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -55,7 +55,7 @@ use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, InnerSpan, Span, SyntaxContext}; +use rustc_span::{BytePos, InnerSpan, Span}; use rustc_target::abi::{Abi, VariantIdx}; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult}; @@ -2184,7 +2184,7 @@ impl ExplicitOutlivesRequirements { tcx: TyCtxt<'tcx>, bounds: &hir::GenericBounds<'_>, inferred_outlives: &[ty::Region<'tcx>], - span_cx: SyntaxContext, + predicate_span: Span, ) -> Vec<(usize, Span)> { use rustc_middle::middle::resolve_lifetime::Region; @@ -2207,8 +2207,8 @@ impl ExplicitOutlivesRequirements { return None; } - let span = bound.span(); - if span.ctxt() != span_cx || in_external_macro(tcx.sess, span) { + let span = bound.span().find_ancestor_inside(predicate_span)?; + if in_external_macro(tcx.sess, span) { return None; } @@ -2279,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_lifetime::Region; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, ref hir_generics) - | hir::ItemKind::Enum(_, ref hir_generics) - | hir::ItemKind::Union(_, ref hir_generics) = item.kind + if let hir::ItemKind::Struct(_, hir_generics) + | hir::ItemKind::Enum(_, hir_generics) + | hir::ItemKind::Union(_, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2296,47 +2296,48 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let mut dropped_predicate_count = 0; let num_predicates = hir_generics.predicates.len(); for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { - let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate { - hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(region_def_id)) = - cx.tcx.named_region(predicate.lifetime.hir_id) - { - ( - Self::lifetimes_outliving_lifetime( - inferred_outlives, - region_def_id, - ), - &predicate.bounds, - predicate.span, - predicate.in_where_clause, - ) - } else { - continue; - } - } - hir::WherePredicate::BoundPredicate(predicate) => { - // FIXME we can also infer bounds on associated types, - // and should check for them here. - match predicate.bounded_ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { - let Res::Def(DefKind::TyParam, def_id) = path.res else { - continue; - }; - let index = ty_generics.param_def_id_to_index[&def_id]; + let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = + match where_predicate { + hir::WherePredicate::RegionPredicate(predicate) => { + if let Some(Region::EarlyBound(region_def_id)) = + cx.tcx.named_region(predicate.lifetime.hir_id) + { ( - Self::lifetimes_outliving_type(inferred_outlives, index), + Self::lifetimes_outliving_lifetime( + inferred_outlives, + region_def_id, + ), &predicate.bounds, predicate.span, - predicate.origin == PredicateOrigin::WhereClause, + predicate.in_where_clause, ) - } - _ => { + } else { continue; } } - } - _ => continue, - }; + hir::WherePredicate::BoundPredicate(predicate) => { + // FIXME we can also infer bounds on associated types, + // and should check for them here. + match predicate.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue; + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + predicate.origin == PredicateOrigin::WhereClause, + ) + } + _ => { + continue; + } + } + } + _ => continue, + }; if relevant_lifetimes.is_empty() { continue; } @@ -2345,7 +2346,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { cx.tcx, bounds, &relevant_lifetimes, - span.ctxt(), + predicate_span, ); bound_count += bound_spans.len(); @@ -2355,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } if drop_predicate && !in_where_clause { - lint_spans.push(span); + lint_spans.push(predicate_span); } else if drop_predicate && i + 1 < num_predicates { // If all the bounds on a predicate were inferable and there are // further predicates, we want to eat the trailing comma. let next_predicate_span = hir_generics.predicates[i + 1].span(); - where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo())); + where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo())); } else { where_lint_spans.extend(self.consolidate_outlives_bound_spans( - span.shrink_to_lo(), + predicate_span.shrink_to_lo(), bounds, bound_spans, )); @@ -2384,12 +2385,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } else { hir_generics.span.shrink_to_hi().to(where_span) }; - lint_spans.push(full_where_span); + + // Due to macro expansions, the `full_where_span` might not actually contain all predicates. + if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) { + lint_spans.push(full_where_span); + } else { + lint_spans.extend(where_lint_spans); + } } else { lint_spans.extend(where_lint_spans); } if !lint_spans.is_empty() { + // Do not automatically delete outlives requirements from macros. + let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions()) + { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + cx.struct_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), @@ -2397,11 +2412,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { |lint| { lint.set_arg("count", bound_count).multipart_suggestion( fluent::suggestion, - lint_spans - .into_iter() - .map(|span| (span, String::new())) - .collect::<Vec<_>>(), - Applicability::MachineApplicable, + lint_spans.into_iter().map(|span| (span, String::new())).collect(), + applicability, ) }, ); |
