Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix span for non-satisfied trivial trait bounds #90884

Merged
merged 1 commit into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation};
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>,
Expand Down Expand Up @@ -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>>,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError}
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::{
Expand Down
25 changes: 22 additions & 3 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 4 additions & 5 deletions src/test/ui/const-generics/issues/issue-67185-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
{
}

Expand Down
60 changes: 24 additions & 36 deletions src/test/ui/const-generics/issues/issue-67185-2.stderr
Original file line number Diff line number Diff line change
@@ -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]`
Comment on lines 1 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this should have a secondary span pointing at line 5, but that can be accomplished with maybe a new ObligationCauseCode (or maybe an ImplObligation).

|
= help: the following implementations were found:
<[[u16; 3]; 3] as Bar>
Expand All @@ -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>
Expand All @@ -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]`
Expand All @@ -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]`
Expand All @@ -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]`
Expand All @@ -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]`
Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/cross/cross-fn-cache-hole.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 3 additions & 9 deletions src/test/ui/cross/cross-fn-cache-hole.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading