Some ordering and duplication checks
This commit is contained in:
parent
02d7317af2
commit
ce8961039e
7 changed files with 140 additions and 15 deletions
|
@ -113,6 +113,9 @@ hir_analysis_drop_impl_on_wrong_item =
|
|||
|
||||
hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
|
||||
|
||||
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
|
||||
.label = parameter captured again here
|
||||
|
||||
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
|
||||
.note = impl is a specialization of this impl
|
||||
|
||||
|
@ -216,6 +219,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
|
|||
hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
|
||||
.label = type parameter declared here
|
||||
|
||||
hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
|
||||
.label = move the lifetime before this parameter
|
||||
|
||||
hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
|
||||
.label = lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
||||
.param_label = this lifetime parameter is captured
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::compare_impl_item::check_type_bounds;
|
|||
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
|
||||
use super::*;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::{codes::*, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
|
@ -484,22 +484,51 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
|
|||
};
|
||||
|
||||
let mut expected_captures = UnordSet::default();
|
||||
let mut seen_params = UnordMap::default();
|
||||
let mut prev_non_lifetime_param = None;
|
||||
for arg in precise_capturing_args {
|
||||
match *arg {
|
||||
hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, .. })
|
||||
| hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
|
||||
hir_id, ..
|
||||
}) => match tcx.named_bound_var(hir_id) {
|
||||
Some(ResolvedArg::EarlyBound(def_id)) => {
|
||||
expected_captures.insert(def_id);
|
||||
let (hir_id, ident) = match *arg {
|
||||
hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
|
||||
hir_id,
|
||||
ident,
|
||||
..
|
||||
}) => {
|
||||
if prev_non_lifetime_param.is_none() {
|
||||
prev_non_lifetime_param = Some(ident);
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.hir().span(hir_id),
|
||||
"parameter should have been resolved",
|
||||
);
|
||||
(hir_id, ident)
|
||||
}
|
||||
hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, ident, .. }) => {
|
||||
if let Some(prev_non_lifetime_param) = prev_non_lifetime_param {
|
||||
tcx.dcx().emit_err(errors::LifetimesMustBeFirst {
|
||||
lifetime_span: ident.span,
|
||||
name: ident.name,
|
||||
other_span: prev_non_lifetime_param.span,
|
||||
});
|
||||
}
|
||||
},
|
||||
(hir_id, ident)
|
||||
}
|
||||
};
|
||||
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
if let Some(span) = seen_params.insert(ident, ident.span) {
|
||||
tcx.dcx().emit_err(errors::DuplicatePreciseCapture {
|
||||
name: ident.name,
|
||||
first_span: span,
|
||||
second_span: ident.span,
|
||||
});
|
||||
}
|
||||
|
||||
match tcx.named_bound_var(hir_id) {
|
||||
Some(ResolvedArg::EarlyBound(def_id)) => {
|
||||
expected_captures.insert(def_id);
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.hir().span(hir_id),
|
||||
"parameter should have been resolved",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_param_not_captured)]
|
||||
|
@ -31,3 +31,23 @@ pub struct BadPreciseCapture {
|
|||
pub kind: &'static str,
|
||||
pub found: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_duplicate_precise_capture)]
|
||||
pub struct DuplicatePreciseCapture {
|
||||
#[primary_span]
|
||||
pub first_span: Span,
|
||||
pub name: Symbol,
|
||||
#[label]
|
||||
pub second_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_lifetime_must_be_first)]
|
||||
pub struct LifetimesMustBeFirst {
|
||||
#[primary_span]
|
||||
pub lifetime_span: Span,
|
||||
pub name: Symbol,
|
||||
#[label]
|
||||
pub other_span: Span,
|
||||
}
|
||||
|
|
4
tests/ui/feature-gates/feature-gate-precise-capturing.rs
Normal file
4
tests/ui/feature-gates/feature-gate-precise-capturing.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
fn hello() -> impl use<> Sized {}
|
||||
//~^ ERROR precise captures on `impl Trait` are experimental
|
||||
|
||||
fn main() {}
|
13
tests/ui/feature-gates/feature-gate-precise-capturing.stderr
Normal file
13
tests/ui/feature-gates/feature-gate-precise-capturing.stderr
Normal file
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: precise captures on `impl Trait` are experimental
|
||||
--> $DIR/feature-gate-precise-capturing.rs:1:20
|
||||
|
|
||||
LL | fn hello() -> impl use<> Sized {}
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
|
||||
= help: add `#![feature(precise_capturing)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
16
tests/ui/impl-trait/precise-capturing/ordering.rs
Normal file
16
tests/ui/impl-trait/precise-capturing/ordering.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#![feature(precise_capturing)]
|
||||
//~^ WARN the feature `precise_capturing` is incomplete
|
||||
|
||||
fn lt<'a>() -> impl use<'a, 'a> Sized {}
|
||||
//~^ ERROR cannot capture parameter `'a` twice
|
||||
|
||||
fn ty<T>() -> impl use<T, T> Sized {}
|
||||
//~^ ERROR cannot capture parameter `T` twice
|
||||
|
||||
fn ct<const N: usize>() -> impl use<N, N> Sized {}
|
||||
//~^ ERROR cannot capture parameter `N` twice
|
||||
|
||||
fn ordering<'a, T>() -> impl use<T, 'a> Sized {}
|
||||
//~^ ERROR lifetime parameter `'a` must be listed before non-lifetime parameters
|
||||
|
||||
fn main() {}
|
37
tests/ui/impl-trait/precise-capturing/ordering.stderr
Normal file
37
tests/ui/impl-trait/precise-capturing/ordering.stderr
Normal file
|
@ -0,0 +1,37 @@
|
|||
warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/ordering.rs:1: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: cannot capture parameter `'a` twice
|
||||
--> $DIR/ordering.rs:4:25
|
||||
|
|
||||
LL | fn lt<'a>() -> impl use<'a, 'a> Sized {}
|
||||
| ^^ -- parameter captured again here
|
||||
|
||||
error: cannot capture parameter `T` twice
|
||||
--> $DIR/ordering.rs:7:24
|
||||
|
|
||||
LL | fn ty<T>() -> impl use<T, T> Sized {}
|
||||
| ^ - parameter captured again here
|
||||
|
||||
error: cannot capture parameter `N` twice
|
||||
--> $DIR/ordering.rs:10:37
|
||||
|
|
||||
LL | fn ct<const N: usize>() -> impl use<N, N> Sized {}
|
||||
| ^ - parameter captured again here
|
||||
|
||||
error: lifetime parameter `'a` must be listed before non-lifetime parameters
|
||||
--> $DIR/ordering.rs:13:37
|
||||
|
|
||||
LL | fn ordering<'a, T>() -> impl use<T, 'a> Sized {}
|
||||
| - ^^
|
||||
| |
|
||||
| move the lifetime before this parameter
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
Loading…
Add table
Reference in a new issue