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
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>,
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>>,
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::{
/// 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,
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]
{
}
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>
= 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>
= 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]`
<[[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]`
<[[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]`
<[[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]`
<[[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
// 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
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
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`
= 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)>`
= 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