Detect duplicates

This commit is contained in:
Michael Goulet 2024-06-05 16:43:25 -04:00
parent f66558d2bf
commit 2e03130e11
7 changed files with 78 additions and 8 deletions

View File

@ -1531,10 +1531,13 @@ fn lower_opaque_impl_trait(
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
let captured_lifetimes_to_duplicate = if let Some(args) = let captured_lifetimes_to_duplicate = if let Some(args) =
bounds.iter().find_map(|bound| match bound { // We only look for one `use<...>` syntax since we syntactially reject more than one.
bounds.iter().find_map(
|bound| match bound {
ast::GenericBound::Use(a, _) => Some(a), ast::GenericBound::Use(a, _) => Some(a),
_ => None, _ => None,
}) { },
) {
// We'll actually validate these later on; all we need is the list of // We'll actually validate these later on; all we need is the list of
// lifetimes to duplicate during this portion of lowering. // lifetimes to duplicate during this portion of lowering.
args.iter() args.iter()

View File

@ -14,8 +14,6 @@ ast_passes_assoc_type_without_body =
associated type in `impl` without body associated type in `impl` without body
.suggestion = provide a definition for the type .suggestion = provide a definition for the type
ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc}
ast_passes_at_least_one_trait = at least one trait must be specified ast_passes_at_least_one_trait = at least one trait must be specified
ast_passes_auto_generic = auto traits cannot have generic parameters ast_passes_auto_generic = auto traits cannot have generic parameters
@ -217,6 +215,11 @@ ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer t
ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
.label = pattern not allowed in foreign function .label = pattern not allowed in foreign function
ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing syntax
.label = second `use<...>` here
ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc}
ast_passes_show_span = {$msg} ast_passes_show_span = {$msg}
ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library

View File

@ -193,8 +193,24 @@ fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
// Mirrors `visit::walk_ty`, but tracks relevant state. // Mirrors `visit::walk_ty`, but tracks relevant state.
fn walk_ty(&mut self, t: &'a Ty) { fn walk_ty(&mut self, t: &'a Ty) {
match &t.kind { match &t.kind {
TyKind::ImplTrait(..) => { TyKind::ImplTrait(_, bounds) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
// FIXME(precise_capturing): If we were to allow `use` in other positions
// (e.g. GATs), then we must validate those as well. However, we don't have
// a good way of doing this with the current `Visitor` structure.
let mut use_bounds = bounds
.iter()
.filter_map(|bound| match bound {
GenericBound::Use(_, span) => Some(span),
_ => None,
})
.copied();
if let Some(bound1) = use_bounds.next()
&& let Some(bound2) = use_bounds.next()
{
self.dcx().emit_err(errors::DuplicatePreciseCapturing { bound1, bound2 });
}
} }
TyKind::TraitObject(..) => self TyKind::TraitObject(..) => self
.with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { .with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| {

View File

@ -852,3 +852,12 @@ pub struct PreciseCapturingNotAllowedHere {
pub span: Span, pub span: Span,
pub loc: &'static str, pub loc: &'static str,
} }
#[derive(Diagnostic)]
#[diag(ast_passes_precise_capturing_duplicated)]
pub struct DuplicatePreciseCapturing {
#[primary_span]
pub bound1: Span,
#[label]
pub bound2: Span,
}

View File

@ -0,0 +1,11 @@
warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/duplicated-use.rs:4:12
|
LL | #![feature(precise_capturing)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -0,0 +1,17 @@
error: duplicate `use<...>` precise capturing syntax
--> $DIR/duplicated-use.rs:8:32
|
LL | fn hello<'a>() -> impl Sized + use<'a> + use<'a> {}
| ^^^^^^^ ------- second `use<...>` here
warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/duplicated-use.rs:4:12
|
LL | #![feature(precise_capturing)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
= note: `#[warn(incomplete_features)]` on by default
error: aborting due to 1 previous error; 1 warning emitted

View File

@ -0,0 +1,11 @@
//@ revisions: real pre_expansion
//@[pre_expansion] check-pass
#![feature(precise_capturing)]
//~^ WARN the feature `precise_capturing` is incomplete
#[cfg(real)]
fn hello<'a>() -> impl Sized + use<'a> + use<'a> {}
//[real]~^ ERROR duplicate `use<...>` precise capturing syntax
fn main() {}