Skip to content

Commit 1eba6c4

Browse files
author
Lukas Markeffsky
committed
address review comments + better tests
1 parent 83e6539 commit 1eba6c4

File tree

6 files changed

+405
-98
lines changed

6 files changed

+405
-98
lines changed

compiler/rustc_ast_lowering/src/item.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13161316
param.id,
13171317
&param.kind,
13181318
&param.bounds,
1319+
param.colon_span,
1320+
generics.span,
13191321
itctx,
13201322
PredicateOrigin::GenericParam,
13211323
)
@@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13651367
id: NodeId,
13661368
kind: &GenericParamKind,
13671369
bounds: &[GenericBound],
1370+
colon_span: Option<Span>,
1371+
parent_span: Span,
13681372
itctx: &ImplTraitContext,
13691373
origin: PredicateOrigin,
13701374
) -> Option<hir::WherePredicate<'hir>> {
@@ -1377,8 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
13771381

13781382
let ident = self.lower_ident(ident);
13791383
let param_span = ident.span;
1380-
let span =
1381-
bounds.iter().fold(param_span.shrink_to_hi(), |span, bound| span.to(bound.span()));
1384+
1385+
// Reconstruct the span of the entire predicate from the individual generic bounds.
1386+
let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
1387+
let span = bounds.iter().fold(span_start, |span_accum, bound| {
1388+
match bound.span().find_ancestor_inside(parent_span) {
1389+
Some(bound_span) => span_accum.to(bound_span),
1390+
None => span_accum,
1391+
}
1392+
});
1393+
let span = self.lower_span(span);
1394+
13821395
match kind {
13831396
GenericParamKind::Const { .. } => None,
13841397
GenericParamKind::Type { .. } => {

compiler/rustc_ast_lowering/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2247,14 +2247,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22472247
) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) {
22482248
// Add a definition for the in-band `Param`.
22492249
let def_id = self.local_def_id(node_id);
2250+
let span = self.lower_span(span);
22502251

22512252
// Set the name to `impl Bound1 + Bound2`.
22522253
let param = hir::GenericParam {
22532254
hir_id: self.lower_node_id(node_id),
22542255
def_id,
22552256
name: ParamName::Plain(self.lower_ident(ident)),
22562257
pure_wrt_drop: false,
2257-
span: self.lower_span(span),
2258+
span,
22582259
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
22592260
colon_span: None,
22602261
};
@@ -2264,6 +2265,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22642265
node_id,
22652266
&GenericParamKind::Type { default: None },
22662267
bounds,
2268+
/* colon_span */ None,
2269+
span,
22672270
&ImplTraitContext::Universal,
22682271
hir::PredicateOrigin::ImplTrait,
22692272
);
@@ -2273,7 +2276,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22732276
let ty = hir::TyKind::Path(hir::QPath::Resolved(
22742277
None,
22752278
self.arena.alloc(hir::Path {
2276-
span: self.lower_span(span),
2279+
span,
22772280
res,
22782281
segments:
22792282
arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],

compiler/rustc_lint/src/builtin.rs

+63-51
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
5555
use rustc_span::edition::Edition;
5656
use rustc_span::source_map::Spanned;
5757
use rustc_span::symbol::{kw, sym, Ident, Symbol};
58-
use rustc_span::{BytePos, InnerSpan, Span, SyntaxContext};
58+
use rustc_span::{BytePos, InnerSpan, Span};
5959
use rustc_target::abi::{Abi, VariantIdx};
6060
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
6161
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
@@ -2184,7 +2184,7 @@ impl ExplicitOutlivesRequirements {
21842184
tcx: TyCtxt<'tcx>,
21852185
bounds: &hir::GenericBounds<'_>,
21862186
inferred_outlives: &[ty::Region<'tcx>],
2187-
span_cx: SyntaxContext,
2187+
predicate_span: Span,
21882188
) -> Vec<(usize, Span)> {
21892189
use rustc_middle::middle::resolve_lifetime::Region;
21902190

@@ -2207,8 +2207,8 @@ impl ExplicitOutlivesRequirements {
22072207
return None;
22082208
}
22092209

2210-
let span = bound.span();
2211-
if span.ctxt() != span_cx || in_external_macro(tcx.sess, span) {
2210+
let span = bound.span().find_ancestor_inside(predicate_span)?;
2211+
if in_external_macro(tcx.sess, span) {
22122212
return None;
22132213
}
22142214

@@ -2279,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22792279
use rustc_middle::middle::resolve_lifetime::Region;
22802280

22812281
let def_id = item.owner_id.def_id;
2282-
if let hir::ItemKind::Struct(_, ref hir_generics)
2283-
| hir::ItemKind::Enum(_, ref hir_generics)
2284-
| hir::ItemKind::Union(_, ref hir_generics) = item.kind
2282+
if let hir::ItemKind::Struct(_, hir_generics)
2283+
| hir::ItemKind::Enum(_, hir_generics)
2284+
| hir::ItemKind::Union(_, hir_generics) = item.kind
22852285
{
22862286
let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
22872287
if inferred_outlives.is_empty() {
@@ -2296,47 +2296,48 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22962296
let mut dropped_predicate_count = 0;
22972297
let num_predicates = hir_generics.predicates.len();
22982298
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
2299-
let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
2300-
hir::WherePredicate::RegionPredicate(predicate) => {
2301-
if let Some(Region::EarlyBound(region_def_id)) =
2302-
cx.tcx.named_region(predicate.lifetime.hir_id)
2303-
{
2304-
(
2305-
Self::lifetimes_outliving_lifetime(
2306-
inferred_outlives,
2307-
region_def_id,
2308-
),
2309-
&predicate.bounds,
2310-
predicate.span,
2311-
predicate.in_where_clause,
2312-
)
2313-
} else {
2314-
continue;
2315-
}
2316-
}
2317-
hir::WherePredicate::BoundPredicate(predicate) => {
2318-
// FIXME we can also infer bounds on associated types,
2319-
// and should check for them here.
2320-
match predicate.bounded_ty.kind {
2321-
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2322-
let Res::Def(DefKind::TyParam, def_id) = path.res else {
2323-
continue;
2324-
};
2325-
let index = ty_generics.param_def_id_to_index[&def_id];
2299+
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
2300+
match where_predicate {
2301+
hir::WherePredicate::RegionPredicate(predicate) => {
2302+
if let Some(Region::EarlyBound(region_def_id)) =
2303+
cx.tcx.named_region(predicate.lifetime.hir_id)
2304+
{
23262305
(
2327-
Self::lifetimes_outliving_type(inferred_outlives, index),
2306+
Self::lifetimes_outliving_lifetime(
2307+
inferred_outlives,
2308+
region_def_id,
2309+
),
23282310
&predicate.bounds,
23292311
predicate.span,
2330-
predicate.origin == PredicateOrigin::WhereClause,
2312+
predicate.in_where_clause,
23312313
)
2332-
}
2333-
_ => {
2314+
} else {
23342315
continue;
23352316
}
23362317
}
2337-
}
2338-
_ => continue,
2339-
};
2318+
hir::WherePredicate::BoundPredicate(predicate) => {
2319+
// FIXME we can also infer bounds on associated types,
2320+
// and should check for them here.
2321+
match predicate.bounded_ty.kind {
2322+
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2323+
let Res::Def(DefKind::TyParam, def_id) = path.res else {
2324+
continue;
2325+
};
2326+
let index = ty_generics.param_def_id_to_index[&def_id];
2327+
(
2328+
Self::lifetimes_outliving_type(inferred_outlives, index),
2329+
&predicate.bounds,
2330+
predicate.span,
2331+
predicate.origin == PredicateOrigin::WhereClause,
2332+
)
2333+
}
2334+
_ => {
2335+
continue;
2336+
}
2337+
}
2338+
}
2339+
_ => continue,
2340+
};
23402341
if relevant_lifetimes.is_empty() {
23412342
continue;
23422343
}
@@ -2345,7 +2346,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23452346
cx.tcx,
23462347
bounds,
23472348
&relevant_lifetimes,
2348-
span.ctxt(),
2349+
predicate_span,
23492350
);
23502351
bound_count += bound_spans.len();
23512352

@@ -2355,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23552356
}
23562357

23572358
if drop_predicate && !in_where_clause {
2358-
lint_spans.push(span);
2359+
lint_spans.push(predicate_span);
23592360
} else if drop_predicate && i + 1 < num_predicates {
23602361
// If all the bounds on a predicate were inferable and there are
23612362
// further predicates, we want to eat the trailing comma.
23622363
let next_predicate_span = hir_generics.predicates[i + 1].span();
2363-
where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo()));
2364+
where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo()));
23642365
} else {
23652366
where_lint_spans.extend(self.consolidate_outlives_bound_spans(
2366-
span.shrink_to_lo(),
2367+
predicate_span.shrink_to_lo(),
23672368
bounds,
23682369
bound_spans,
23692370
));
@@ -2384,24 +2385,35 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23842385
} else {
23852386
hir_generics.span.shrink_to_hi().to(where_span)
23862387
};
2387-
lint_spans.push(full_where_span);
2388+
2389+
// Due to macro expansions, the `full_where_span` might not actually contain all predicates.
2390+
if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) {
2391+
lint_spans.push(full_where_span);
2392+
} else {
2393+
lint_spans.extend(where_lint_spans);
2394+
}
23882395
} else {
23892396
lint_spans.extend(where_lint_spans);
23902397
}
23912398

23922399
if !lint_spans.is_empty() {
2400+
// Do not automatically delete outlives requirements from macros.
2401+
let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions())
2402+
{
2403+
Applicability::MachineApplicable
2404+
} else {
2405+
Applicability::MaybeIncorrect
2406+
};
2407+
23932408
cx.struct_span_lint(
23942409
EXPLICIT_OUTLIVES_REQUIREMENTS,
23952410
lint_spans.clone(),
23962411
fluent::lint_builtin_explicit_outlives,
23972412
|lint| {
23982413
lint.set_arg("count", bound_count).multipart_suggestion(
23992414
fluent::suggestion,
2400-
lint_spans
2401-
.into_iter()
2402-
.map(|span| (span, String::new()))
2403-
.collect::<Vec<_>>(),
2404-
Applicability::MachineApplicable,
2415+
lint_spans.into_iter().map(|span| (span, String::new())).collect(),
2416+
applicability,
24052417
)
24062418
},
24072419
);

0 commit comments

Comments
 (0)