]> git.lizzy.rs Git - rust.git/commitdiff
Fix span for non-satisfied trivial trait bounds
authorNilstrieb <48135649+Nilstrieb@users.noreply.github.com>
Sat, 13 Nov 2021 22:56:22 +0000 (23:56 +0100)
committerNilstrieb <48135649+Nilstrieb@users.noreply.github.com>
Sun, 14 Nov 2021 10:38:52 +0000 (11:38 +0100)
The spans for "trait bound not satisfied" errors in trivial trait bounds referenced the entire item (fn, impl, struct) before.
Now they only reference the obligation itself (`String: Copy`)

Address #90869

compiler/rustc_infer/src/traits/util.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_typeck/src/check/wfcheck.rs
src/test/ui/const-generics/issues/issue-67185-2.rs
src/test/ui/const-generics/issues/issue-67185-2.stderr
src/test/ui/cross/cross-fn-cache-hole.rs
src/test/ui/cross/cross-fn-cache-hole.stderr
src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr

index c839f824d1c9c57501111431e430180269c3c517..92f74af4eb3eb930959168337dd0911572a85803 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
 use rustc_span::symbol::Ident;
+use rustc_span::Span;
 
 pub fn anonymize_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -97,6 +98,22 @@ pub fn elaborate_predicates<'tcx>(
     elaborate_obligations(tcx, obligations)
 }
 
+pub fn elaborate_predicates_with_span<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
+) -> Elaborator<'tcx> {
+    let obligations = predicates
+        .map(|(predicate, span)| {
+            predicate_obligation(
+                predicate,
+                ty::ParamEnv::empty(),
+                ObligationCause::dummy_with_span(span),
+            )
+        })
+        .collect();
+    elaborate_obligations(tcx, obligations)
+}
+
 pub fn elaborate_obligations<'tcx>(
     tcx: TyCtxt<'tcx>,
     mut obligations: Vec<PredicateObligation<'tcx>>,
index d4a586b0124a20b1bd790bebc98f0ccc991f0611..91671994c5ace9c87c31ddc0e1750a7277244ae4 100644 (file)
@@ -65,7 +65,8 @@
 pub use self::structural_match::search_for_structural_match_violation;
 pub use self::structural_match::NonStructuralMatchTy;
 pub use self::util::{
-    elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs,
+    elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
+    elaborate_trait_ref, elaborate_trait_refs,
 };
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{
index c1adc2894ccfcd365541de28932c886fb71ae4f5..0050ac99cb19a8c32ac804792a94b2ec2b099783 100644 (file)
@@ -1641,19 +1641,38 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) {
 
 /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
 /// aren't true.
-fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
+fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirId) {
     let empty_env = ty::ParamEnv::empty();
 
     let def_id = fcx.tcx.hir().local_def_id(id);
-    let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p);
+    let predicates_with_span =
+        fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, span)| (*p, *span));
     // Check elaborated bounds.
-    let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
+    let implied_obligations = traits::elaborate_predicates_with_span(fcx.tcx, predicates_with_span);
 
     for obligation in implied_obligations {
         let pred = obligation.predicate;
         // Match the existing behavior.
         if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
             let pred = fcx.normalize_associated_types_in(span, pred);
+            let hir_node = fcx.tcx.hir().find(id);
+
+            // only use the span of the predicate clause (#90869)
+
+            if let Some(hir::Generics { where_clause, .. }) =
+                hir_node.and_then(|node| node.generics())
+            {
+                let obligation_span = obligation.cause.span(fcx.tcx);
+
+                span = where_clause
+                    .predicates
+                    .iter()
+                    // There seems to be no better way to find out which predicate we are in
+                    .find(|pred| pred.span().contains(obligation_span))
+                    .map(|pred| pred.span())
+                    .unwrap_or(obligation_span);
+            }
+
             let obligation = traits::Obligation::new(
                 traits::ObligationCause::new(span, id, traits::TrivialBound),
                 empty_env,
index c1a04e201474959f41e926c61b20c4579de57725..18bb6f6bc1edc4884d65cd5155f87cbdbf94ebdc 100644 (file)
@@ -9,11 +9,10 @@ trait Bar {}
 impl Bar for [u16; 4] {}
 impl Bar for [[u16; 3]; 3] {}
 
-trait Foo  //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277]
-           //~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277]
-    where
-        [<u8 as Baz>::Quaks; 2]: Bar,
-        <u8 as Baz>::Quaks: Bar,
+trait Foo
+where
+    [<u8 as Baz>::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277]
+    <u8 as Baz>::Quaks: Bar,  //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277]
 {
 }
 
index 7167bea94bbb68b8a0f88487cef871016b449ac5..89aa3d395e25bb8eae63133c28f02e1ee774cad5 100644 (file)
@@ -1,14 +1,8 @@
 error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:12:1
+  --> $DIR/issue-67185-2.rs:15:5
    |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[u16; 3]`
+LL |     <u8 as Baz>::Quaks: Bar,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]`
    |
    = help: the following implementations were found:
              <[[u16; 3]; 3] as Bar>
@@ -17,16 +11,10 @@ LL | | }
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:12:1
+  --> $DIR/issue-67185-2.rs:14:5
    |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
+LL |     [<u8 as Baz>::Quaks; 2]: Bar,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
    |
    = help: the following implementations were found:
              <[[u16; 3]; 3] as Bar>
@@ -35,7 +23,7 @@ LL | | }
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:22:6
+  --> $DIR/issue-67185-2.rs:21:6
    |
 LL | impl Foo for FooImpl {}
    |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`
@@ -44,16 +32,16 @@ LL | impl Foo for FooImpl {}
              <[[u16; 3]; 3] as Bar>
              <[u16; 4] as Bar>
 note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:16:29
+  --> $DIR/issue-67185-2.rs:15:25
    |
 LL | trait Foo
    |       --- required by a bound in this
 ...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
+LL |     <u8 as Baz>::Quaks: Bar,
+   |                         ^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:22:6
+  --> $DIR/issue-67185-2.rs:21:6
    |
 LL | impl Foo for FooImpl {}
    |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
@@ -62,16 +50,16 @@ LL | impl Foo for FooImpl {}
              <[[u16; 3]; 3] as Bar>
              <[u16; 4] as Bar>
 note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:15:34
+  --> $DIR/issue-67185-2.rs:14:30
    |
 LL | trait Foo
    |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
+LL | where
+LL |     [<u8 as Baz>::Quaks; 2]: Bar,
+   |                              ^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:14
+  --> $DIR/issue-67185-2.rs:25:14
    |
 LL | fn f(_: impl Foo) {}
    |              ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
@@ -80,16 +68,16 @@ LL | fn f(_: impl Foo) {}
              <[[u16; 3]; 3] as Bar>
              <[u16; 4] as Bar>
 note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:15:34
+  --> $DIR/issue-67185-2.rs:14:30
    |
 LL | trait Foo
    |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
+LL | where
+LL |     [<u8 as Baz>::Quaks; 2]: Bar,
+   |                              ^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:14
+  --> $DIR/issue-67185-2.rs:25:14
    |
 LL | fn f(_: impl Foo) {}
    |              ^^^ the trait `Bar` is not implemented for `[u16; 3]`
@@ -98,13 +86,13 @@ LL | fn f(_: impl Foo) {}
              <[[u16; 3]; 3] as Bar>
              <[u16; 4] as Bar>
 note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:16:29
+  --> $DIR/issue-67185-2.rs:15:25
    |
 LL | trait Foo
    |       --- required by a bound in this
 ...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
+LL |     <u8 as Baz>::Quaks: Bar,
+   |                         ^^^ required by this bound in `Foo`
 
 error: aborting due to 6 previous errors
 
index 249c6474c94206ec499aee3c2c3536b13fd0477d..c38a5001ac86d18c30d068eca0fa0ac0cd055424 100644 (file)
@@ -12,8 +12,8 @@ trait Bar<X> { }
 
 // We don't always check where clauses for sanity, but in this case
 // wfcheck does report an error here:
-fn vacuous<A>() //~ ERROR the trait bound `i32: Bar<u32>` is not satisfied
-    where i32: Foo<u32, A>
+fn vacuous<A>()
+    where i32: Foo<u32, A> //~ ERROR the trait bound `i32: Bar<u32>` is not satisfied
 {
     // ... the original intention was to check that we don't use that
     // vacuous where clause (which could never be satisfied) to accept
index 0d325bb7ec102089cd9c6fe6649dfdcd66c77619..7e15562b0816b38759feaa4f8b5a99f776bc0f21 100644 (file)
@@ -1,14 +1,8 @@
 error[E0277]: the trait bound `i32: Bar<u32>` is not satisfied
-  --> $DIR/cross-fn-cache-hole.rs:15:1
+  --> $DIR/cross-fn-cache-hole.rs:16:11
    |
-LL | / fn vacuous<A>()
-LL | |     where i32: Foo<u32, A>
-LL | | {
-LL | |     // ... the original intention was to check that we don't use that
-...  |
-LL | |     require::<i32, u32>();
-LL | | }
-   | |_^ the trait `Bar<u32>` is not implemented for `i32`
+LL |     where i32: Foo<u32, A>
+   |           ^^^^^^^^^^^^^^^^ the trait `Bar<u32>` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
index 78904b383f49a1c03283afbd652a8e9fdff2f275..28c49c33bf6b5b41caee35a8b9792aaa5e26f458 100644 (file)
@@ -1,87 +1,71 @@
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:10:1
+  --> $DIR/feature-gate-trivial_bounds.rs:10:14
    |
 LL | enum E where i32: Foo { V }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |              ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:12:1
+  --> $DIR/feature-gate-trivial_bounds.rs:12:16
    |
 LL | struct S where i32: Foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |                ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:14:1
+  --> $DIR/feature-gate-trivial_bounds.rs:14:15
    |
 LL | trait T where i32: Foo {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |               ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:16:1
+  --> $DIR/feature-gate-trivial_bounds.rs:16:15
    |
 LL | union U where i32: Foo { f: i32 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+   |               ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:20:1
+  --> $DIR/feature-gate-trivial_bounds.rs:20:23
    |
-LL | / impl Foo for () where i32: Foo {
-LL | |     fn test(&self) {
-LL | |         3i32.test();
-LL | |         Foo::test(&4i32);
-LL | |         generic_function(5i32);
-LL | |     }
-LL | | }
-   | |_^ the trait `Foo` is not implemented for `i32`
+LL | impl Foo for () where i32: Foo {
+   |                       ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:28:1
+  --> $DIR/feature-gate-trivial_bounds.rs:28:14
    |
-LL | / fn f() where i32: Foo
-LL | | {
-LL | |     let s = S;
-LL | |     3i32.test();
-LL | |     Foo::test(&4i32);
-LL | |     generic_function(5i32);
-LL | | }
-   | |_^ the trait `Foo` is not implemented for `i32`
+LL | fn f() where i32: Foo
+   |              ^^^^^^^^ the trait `Foo` is not implemented for `i32`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `String: Neg` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:36:1
+  --> $DIR/feature-gate-trivial_bounds.rs:36:38
    |
-LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
-LL | |     -s
-LL | | }
-   | |_^ the trait `Neg` is not implemented for `String`
+LL | fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Neg` is not implemented for `String`
    |
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: `i32` is not an iterator
-  --> $DIR/feature-gate-trivial_bounds.rs:40:1
+  --> $DIR/feature-gate-trivial_bounds.rs:40:20
    |
-LL | / fn use_for() where i32: Iterator {
-LL | |     for _ in 2i32 {}
-LL | | }
-   | |_^ `i32` is not an iterator
+LL | fn use_for() where i32: Iterator {
+   |                    ^^^^^^^^^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
@@ -89,22 +73,20 @@ LL | | }
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/feature-gate-trivial_bounds.rs:52:1
+  --> $DIR/feature-gate-trivial_bounds.rs:52:32
    |
 LL | struct TwoStrs(str, str) where str: Sized;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                                ^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-trivial_bounds.rs:55:1
+  --> $DIR/feature-gate-trivial_bounds.rs:55:26
    |
-LL | / fn unsized_local() where Dst<dyn A>: Sized {
-LL | |     let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
-LL | | }
-   | |_^ doesn't have a size known at compile-time
+LL | fn unsized_local() where Dst<dyn A>: Sized {
+   |                          ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`
 note: required because it appears within the type `Dst<(dyn A + 'static)>`
@@ -116,12 +98,10 @@ LL | struct Dst<X: ?Sized> {
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/feature-gate-trivial_bounds.rs:59:1
+  --> $DIR/feature-gate-trivial_bounds.rs:59:30
    |
-LL | / fn return_str() -> str where str: Sized {
-LL | |     *"Sized".to_string().into_boxed_str()
-LL | | }
-   | |_^ doesn't have a size known at compile-time
+LL | fn return_str() -> str where str: Sized {
+   |                              ^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = help: see issue #48214