Skip to content

Commit

Permalink
Auto merge of #124228 - compiler-errors:lint-overcaptures, r=oli-obk
Browse files Browse the repository at this point in the history
Warn against changes in opaque lifetime captures in 2024

Adds a (mostly[^1]) machine-applicable lint `IMPL_TRAIT_OVERCAPTURES` which detects cases where we will capture more lifetimes in edition 2024 than in edition <= 2021, which may lead to erroneous borrowck errors.

This lint is gated behind the `precise_capturing` feature gate and marked `Allow` for now.

[^1]: Except when there are APITs -- I may work on that soon

r? oli-obk
  • Loading branch information
bors committed May 14, 2024
2 parents 58426f4 + 052de1d commit c45e831
Show file tree
Hide file tree
Showing 14 changed files with 694 additions and 38 deletions.
15 changes: 9 additions & 6 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
fn_kind,
itctx,
precise_capturing.as_deref().map(|(args, _)| args.as_slice()),
precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)),
),
ImplTraitContext::Universal => {
if let Some(&(_, span)) = precise_capturing.as_deref() {
Expand Down Expand Up @@ -1523,7 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds: &GenericBounds,
fn_kind: Option<FnDeclKind>,
itctx: ImplTraitContext,
precise_capturing_args: Option<&[PreciseCapturingArg]>,
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
Expand All @@ -1533,7 +1533,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);

let captured_lifetimes_to_duplicate =
if let Some(precise_capturing) = precise_capturing_args {
if let Some((precise_capturing, _)) = precise_capturing_args {
// We'll actually validate these later on; all we need is the list of
// lifetimes to duplicate during this portion of lowering.
precise_capturing
Expand Down Expand Up @@ -1607,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
span: Span,
opaque_ty_span: Span,
precise_capturing_args: Option<&[PreciseCapturingArg]>,
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
) -> hir::TyKind<'hir> {
let opaque_ty_def_id = self.create_def(
Expand Down Expand Up @@ -1698,8 +1698,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
this.with_remapping(captured_to_synthesized_mapping, |this| {
(
lower_item_bounds(this),
precise_capturing_args.map(|precise_capturing| {
this.lower_precise_capturing_args(precise_capturing)
precise_capturing_args.map(|(precise_capturing, span)| {
(
this.lower_precise_capturing_args(precise_capturing),
this.lower_span(span),
)
}),
)
});
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2631,7 +2631,7 @@ pub struct OpaqueTy<'hir> {
/// lowered as an associated type.
pub in_trait: bool,
/// List of arguments captured via `impl use<'a, P, ...> Trait` syntax.
pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>,
pub precise_capturing_args: Option<(&'hir [PreciseCapturingArg<'hir>], Span)>,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
Expand All @@ -2641,6 +2641,15 @@ pub enum PreciseCapturingArg<'hir> {
Param(PreciseCapturingNonLifetimeArg),
}

impl PreciseCapturingArg<'_> {
pub fn hir_id(self) -> HirId {
match self {
PreciseCapturingArg::Lifetime(lt) => lt.hir_id,
PreciseCapturingArg::Param(param) => param.hir_id,
}
}
}

/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param
/// resolution to. Lifetimes don't have this problem, and for them, it's actually
/// kind of detrimental to use a custom node type versus just using [`Lifetime`],
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(walk_generics(visitor, generics));
walk_list!(visitor, visit_param_bound, bounds);
if let Some(precise_capturing_args) = precise_capturing_args {
if let Some((precise_capturing_args, _)) = precise_capturing_args {
for arg in precise_capturing_args {
try_visit!(visitor.visit_precise_capturing_arg(arg));
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ fn sanity_check_found_hidden_type<'tcx>(
fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
let hir::OpaqueTy { precise_capturing_args, .. } =
*tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
let Some(precise_capturing_args) = precise_capturing_args else {
let Some((precise_capturing_args, _)) = precise_capturing_args else {
// No precise capturing args; nothing to validate
return;
};
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024
.note = specifically, {$num_captured ->
[one] this lifetime is
*[other] these lifetimes are
} in scope but not mentioned in the type's bounds
.note2 = all lifetimes in scope will be captured by `impl Trait`s in edition 2024
.suggestion = use the precise capturing `use<...>` syntax to make the captures explicit
lint_impl_trait_redundant_captures = all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
.suggestion = remove the `use<...>` syntax
lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
.label = not FFI-safe
.note = the type is defined here
Expand Down
Loading

0 comments on commit c45e831

Please sign in to comment.