about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/builtin.rs37
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs20
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr58
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.fixed9
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.rs9
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.stderr14
6 files changed, 135 insertions, 12 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 6f445426df7..18657c94c58 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2173,13 +2173,31 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     dropped_predicate_count += 1;
                 }
 
-                if drop_predicate && !in_where_clause {
-                    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(predicate_span.to(next_predicate_span.shrink_to_lo()));
+                if drop_predicate {
+                    if !in_where_clause {
+                        lint_spans.push(predicate_span);
+                    } else if predicate_span.from_expansion() {
+                        // Don't try to extend the span if it comes from a macro expansion.
+                        where_lint_spans.push(predicate_span);
+                    } else if 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();
+                        if next_predicate_span.from_expansion() {
+                            where_lint_spans.push(predicate_span);
+                        } else {
+                            where_lint_spans
+                                .push(predicate_span.to(next_predicate_span.shrink_to_lo()));
+                        }
+                    } else {
+                        // Eat the optional trailing comma after the last predicate.
+                        let where_span = hir_generics.where_clause_span;
+                        if where_span.from_expansion() {
+                            where_lint_spans.push(predicate_span);
+                        } else {
+                            where_lint_spans.push(predicate_span.to(where_span.shrink_to_hi()));
+                        }
+                    }
                 } else {
                     where_lint_spans.extend(self.consolidate_outlives_bound_spans(
                         predicate_span.shrink_to_lo(),
@@ -2223,6 +2241,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     Applicability::MaybeIncorrect
                 };
 
+                // Due to macros, there might be several predicates with the same span
+                // and we only want to suggest removing them once.
+                lint_spans.sort_unstable();
+                lint_spans.dedup();
+
                 cx.emit_spanned_lint(
                     EXPLICIT_OUTLIVES_REQUIREMENTS,
                     lint_spans.clone(),
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
index 0b3de0df2b8..d2254acb33f 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
@@ -365,4 +365,24 @@ mod unions {
     }
 }
 
+// https://github.com/rust-lang/rust/issues/106870
+mod multiple_predicates_with_same_span {
+    macro_rules! m {
+        ($($name:ident)+) => {
+            struct Inline<'a, $($name: 'a,)+>(&'a ($($name,)+));
+            //~^ ERROR: outlives requirements can be inferred
+            struct FullWhere<'a, $($name,)+>(&'a ($($name,)+)) where $($name: 'a,)+;
+            //~^ ERROR: outlives requirements can be inferred
+            struct PartialWhere<'a, $($name,)+>(&'a ($($name,)+)) where (): Sized, $($name: 'a,)+;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Interleaved<'a, $($name,)+>(&'a ($($name,)+))
+            where
+                (): Sized,
+                $($name: 'a, $name: 'a, )+ //~ ERROR: outlives requirements can be inferred
+                $($name: 'a, $name: 'a, )+;
+        }
+    }
+    m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+}
+
 fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
index 251d74094ca..f5ec287d291 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
@@ -819,5 +819,61 @@ LL -     union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U:
 LL +     union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug,  {
    |
 
-error: aborting due to 68 previous errors
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:372:38
+   |
+LL |             struct Inline<'a, $($name: 'a,)+>(&'a ($($name,)+));
+   |                                      ^^^^ help: remove these bounds
+...
+LL |     m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+   |     --------------------------------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:374:64
+   |
+LL |             struct FullWhere<'a, $($name,)+>(&'a ($($name,)+)) where $($name: 'a,)+;
+   |                                                                ^^^^^^^^^^^^^^^^^^ help: remove these bounds
+...
+LL |     m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+   |     --------------------------------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:376:86
+   |
+LL |             struct PartialWhere<'a, $($name,)+>(&'a ($($name,)+)) where (): Sized, $($name: 'a,)+;
+   |                                                                                      ^^^^^^^^^ help: remove these bounds
+...
+LL |     m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+   |     --------------------------------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-multispan.rs:381:19
+   |
+LL |                 $($name: 'a, $name: 'a, )+
+   |                   ^^^^^^^^^  ^^^^^^^^^
+LL |                 $($name: 'a, $name: 'a, )+;
+   |                   ^^^^^^^^^  ^^^^^^^^^
+...
+LL |     m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+   |     ---------------------------------------------------------
+   |     |
+   |     in this macro invocation
+   |     in this macro invocation
+   |     in this macro invocation
+   |     in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: remove these bounds
+   |
+LL ~                 $(, , )+
+LL ~                 $(, , )+;
+   |
+
+error: aborting due to 72 previous errors
 
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
index 13645244da0..868bdf2e068 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
@@ -791,5 +791,14 @@ struct StaticRef<T: 'static> {
     field: &'static T
 }
 
+struct TrailingCommaInWhereClause<'a, T, U>
+where
+    T: 'a,
+    
+    //~^ ERROR outlives requirements can be inferred
+{
+    tee: T,
+    yoo: &'a U
+}
 
 fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-infer-outlives.rs
index d9486ba66f8..75783764ad6 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.rs
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.rs
@@ -791,5 +791,14 @@ struct StaticRef<T: 'static> {
     field: &'static T
 }
 
+struct TrailingCommaInWhereClause<'a, T, U>
+where
+    T: 'a,
+    U: 'a,
+    //~^ ERROR outlives requirements can be inferred
+{
+    tee: T,
+    yoo: &'a U
+}
 
 fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
index faa9f21e38b..e655fb4842c 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
@@ -1,8 +1,8 @@
 error: outlives requirements can be inferred
-  --> $DIR/edition-lint-infer-outlives.rs:26:31
+  --> $DIR/edition-lint-infer-outlives.rs:797:5
    |
-LL |     struct TeeOutlivesAy<'a, T: 'a> {
-   |                               ^^^^ help: remove this bound
+LL |     U: 'a,
+   |     ^^^^^^ help: remove this bound
    |
 note: the lint level is defined here
   --> $DIR/edition-lint-infer-outlives.rs:4:9
@@ -11,6 +11,12 @@ LL | #![deny(explicit_outlives_requirements)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives.rs:26:31
+   |
+LL |     struct TeeOutlivesAy<'a, T: 'a> {
+   |                               ^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
   --> $DIR/edition-lint-infer-outlives.rs:31:40
    |
 LL |     struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
@@ -916,5 +922,5 @@ error: outlives requirements can be inferred
 LL |     union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug {
    |                                                            ^^^^^^^^ help: remove this bound
 
-error: aborting due to 152 previous errors
+error: aborting due to 153 previous errors