Skip to content

elaborate obligations in coherence #124532

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

Closed
wants to merge 3 commits into from
Closed
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
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
@@ -121,7 +121,18 @@ pub enum SelectionCandidate<'tcx> {
/// Implementation of transmutability trait.
TransmutabilityCandidate,

ParamCandidate(ty::PolyTraitPredicate<'tcx>),
/// A candidate from the `ParamEnv`.
ParamCandidate {
/// The actual `where`-bound, e.g. `T: Trait`.
predicate: ty::PolyTraitPredicate<'tcx>,
/// `true` if the where-bound has no bound vars and does
/// not refer to any parameters or inference variables.
///
/// We prefer all other candidates over global where-bounds.
/// Notably, global where-bounds do not shadow impls.
is_global: bool,
},

ImplCandidate(DefId),
AutoImplCandidate,

7 changes: 5 additions & 2 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
@@ -358,9 +358,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
) -> IntersectionHasImpossibleObligations<'tcx> {
let infcx = selcx.infcx;

// Elaborate obligations in case the current obligation is unknowable,
// but its super trait bound is not. See #124532 for more details.
let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned());
if infcx.next_trait_solver() {
let ocx = ObligationCtxt::new(infcx);
ocx.register_obligations(obligations.iter().cloned());
ocx.register_obligations(obligations);
let errors_and_ambiguities = ocx.select_all_or_error();
// We only care about the obligations that are *definitely* true errors.
// Ambiguities do not prove the disjointness of two impls.
@@ -387,7 +390,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
for obligation in obligations {
// We use `evaluate_root_obligation` to correctly track intercrate
// ambiguity clauses.
let evaluation_result = selcx.evaluate_root_obligation(obligation);
let evaluation_result = selcx.evaluate_root_obligation(&obligation);

match evaluation_result {
Ok(result) => {
Original file line number Diff line number Diff line change
@@ -251,16 +251,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());

// Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in matching_bounds {
if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity {
for predicate in matching_bounds {
if predicate.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity
{
continue;
}

// FIXME(oli-obk): it is suspicious that we are dropping the constness and
// polarity here.
let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;
let wc = self.where_clause_may_apply(stack, predicate.map_bound(|t| t.trait_ref))?;
if wc.may_apply() {
candidates.vec.push(ParamCandidate(bound));
let is_global = predicate.is_global() && !predicate.has_bound_vars();
candidates.vec.push(ParamCandidate { predicate, is_global });
}
}

Original file line number Diff line number Diff line change
@@ -56,9 +56,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Builtin(BuiltinImplSource::Misc, data)
}

ParamCandidate(param) => {
ParamCandidate { predicate, is_global: _ } => {
let obligations =
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
self.confirm_param_candidate(obligation, predicate.map_bound(|t| t.trait_ref));
ImplSource::Param(obligations)
}

192 changes: 44 additions & 148 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -1575,7 +1575,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return false;
}
match result {
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
Ok(Some(SelectionCandidate::ParamCandidate { predicate, .. })) => {
!predicate.has_infer()
}
_ => true,
}
}
@@ -1827,31 +1829,35 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
return DropVictim::Yes;
}

// Check if a bound would previously have been removed when normalizing
// the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this.
let is_global =
|cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();

// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// `DiscriminantKindCandidate`, `ConstDestructCandidate`
// to anything else.
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
match (&other.candidate, &victim.candidate) {
// FIXME(@jswrenn): this should probably be more sophisticated
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,

// (*)
// Prefer `BuiltinCandidate { has_nested: false }`, `ConstDestructCandidate`
// to anything else.
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
(
BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_),
BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_),
) => bug!("two trivial builtin candidates: {other:?} {victim:?}"),
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
DropVictim::Yes
}
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
DropVictim::No
}

(ParamCandidate(other), ParamCandidate(victim)) => {
// Global bounds from the where clause should be ignored
// here (see issue #50825).
(ParamCandidate { is_global: true, .. }, ParamCandidate { is_global: true, .. }) => {
DropVictim::No
}
(_, ParamCandidate { is_global: true, .. }) => DropVictim::Yes,
(ParamCandidate { is_global: true, .. }, _) => DropVictim::No,

(
ParamCandidate { is_global: false, predicate: other },
ParamCandidate { is_global: false, predicate: victim },
) => {
let same_except_bound_vars = other.skip_binder().trait_ref
== victim.skip_binder().trait_ref
&& other.skip_binder().polarity == victim.skip_binder().polarity
@@ -1868,68 +1874,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}

// Drop otherwise equivalent non-const fn pointer candidates
(FnPointerCandidate { .. }, FnPointerCandidate { fn_host_effect }) => {
DropVictim::drop_if(*fn_host_effect == self.tcx().consts.true_)
}

(
ParamCandidate(ref other_cand),
ImplCandidate(..)
| AutoImplCandidate
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
| TraitAliasCandidate
| ObjectCandidate(_)
| ProjectionCandidate(_),
) => {
// We have a where clause so don't go around looking
// for impls. Arbitrarily give param candidates priority
// over projection and object candidates.
//
// Global bounds from the where clause should be ignored
// here (see issue #50825).
DropVictim::drop_if(!is_global(other_cand))
}
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
// Prefer these to a global where-clause bound
// (see issue #50825).
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
}
(
ImplCandidate(_)
| AutoImplCandidate
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
| TraitAliasCandidate,
ParamCandidate(ref victim_cand),
) => {
// Prefer these to a global where-clause bound
// (see issue #50825).
DropVictim::drop_if(
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(),
)
}
(ParamCandidate { is_global: false, .. }, _) => DropVictim::Yes,
(_, ParamCandidate { is_global: false, .. }) => DropVictim::No,

(ProjectionCandidate(i), ProjectionCandidate(j))
| (ObjectCandidate(i), ObjectCandidate(j)) => {
@@ -1942,44 +1888,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
bug!("Have both object and projection candidate")
}

// Arbitrarily give projection and object candidates priority.
(
ObjectCandidate(_) | ProjectionCandidate(_),
ImplCandidate(..)
| AutoImplCandidate
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
| TraitAliasCandidate,
) => DropVictim::Yes,
// Arbitrarily give projection candidates priority.
(ProjectionCandidate(_), _) => DropVictim::Yes,
(_, ProjectionCandidate(_)) => DropVictim::No,

(
ImplCandidate(..)
| AutoImplCandidate
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
| TraitAliasCandidate,
ObjectCandidate(_) | ProjectionCandidate(_),
) => DropVictim::No,
// Need to prioritize builtin trait object impls as
// `<dyn Any as Any>::type_id` should use the vtable method
// and not the method provided by the user-defined impl
// `impl<T: ?Sized> Any for T { .. }`.
//
// cc #57893
(ObjectCandidate(_), _) => DropVictim::Yes,
(_, ObjectCandidate(_)) => DropVictim::No,

(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
// See if we can toss out `victim` based on specialization.
@@ -2059,49 +1979,25 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}

(AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => {
DropVictim::No
}

(AutoImplCandidate, _) | (_, AutoImplCandidate) => {
bug!(
"default implementations shouldn't be recorded \
when there are other global candidates: {:?} {:?}",
other,
victim
);
}

// Everything else is ambiguous
// Treat all non-trivial builtin impls and user-defined impls the same way.
(
ImplCandidate(_)
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| AutoImplCandidate
| BuiltinCandidate { has_nested: true }
| TraitAliasCandidate,
ImplCandidate(_)
| ClosureCandidate { .. }
| AsyncClosureCandidate
| AsyncFnKindHelperCandidate
| CoroutineCandidate
| FutureCandidate
| IteratorCandidate
| AsyncIteratorCandidate
| FnPointerCandidate { .. }
| BuiltinObjectCandidate
| ClosureCandidate { .. }
| TraitAliasCandidate
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
| TraitAliasCandidate,
| TransmutabilityCandidate
| BuiltinObjectCandidate,
_,
) => DropVictim::No,
}
}
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
@@ -4061,7 +4061,6 @@ ui/traits/issue-6128.rs
ui/traits/issue-6334.rs
ui/traits/issue-65284-suggest-generic-trait-bound.rs
ui/traits/issue-65673.rs
ui/traits/issue-66768.rs
ui/traits/issue-68295.rs
ui/traits/issue-7013.rs
ui/traits/issue-70944.rs
5 changes: 3 additions & 2 deletions tests/ui/associated-item/issue-105449.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//@ check-pass
//@ compile-flags: -C debug_assertions=yes -Zunstable-options

#[allow(dead_code)]
// This is a mutated variant of #66768 which has been removed
// as it no longer tests the original issue.
fn problematic_function<Space>()
where
DefaultAlloc: FinAllok<R1, Space>,
{
let e = Edge2dElement;
let _ = Into::<Point>::into(e.map_reference_coords());
//~^ ERROR the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied
}
impl<N> Allocator<N, R0> for DefaultAlloc {
type Buffer = MStorage;
15 changes: 15 additions & 0 deletions tests/ui/associated-item/issue-105449.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied
--> $DIR/issue-105449.rs:10:33
|
LL | let _ = Into::<Point>::into(e.map_reference_coords());
| ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<(Ure, R1, MStorage)>` is not implemented for `Point`, which is required by `(Ure, R1, MStorage): Into<Point>`
| |
| required by a bound introduced by this call
|
= help: the trait `From<(Ure, Space, <DefaultAlloc as Allocator<Ure, Space>>::Buffer)>` is implemented for `Point`
= help: for that trait implementation, expected `Space`, found `R1`
= note: required for `(Ure, R1, MStorage)` to implement `Into<Point>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ LL | | for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound,
LL | impl<T> Trait for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `<std::boxed::Box<_> as WithAssoc<'a>>::Assoc`
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ LL | | for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound,
LL | impl<T> Trait for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>`
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`

error: aborting due to 1 previous error

1 change: 1 addition & 0 deletions tests/ui/coherence/normalize-for-errors.current.stderr
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Ite
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)`
|
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
= note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions

error: aborting due to 1 previous error

1 change: 1 addition & 0 deletions tests/ui/coherence/normalize-for-errors.rs
Original file line number Diff line number Diff line change
@@ -18,5 +18,6 @@ impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
//~| NOTE conflicting implementation for `(Box<(MyType,)>,
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
//[current]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Added in #124532. While `(): Super` is knowable, `(): Sub<?t>` is not.
//
// We therefore elaborate super trait bounds in the implicit negative
// overlap check.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass

trait Super {}
trait Sub<T>: Super {}

trait Overlap<T> {}
impl<T, U: Sub<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}

fn main() {}
33 changes: 33 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// A regression test for pyella-0.1.5 which broke when
// enabling the new solver in coherence.
//
// `Tensor: TensorValue` is knowable while `Tensor: TensorOp<?t2>`
// may be implemented downstream. We previously didn't check the
// super trait bound in coherence, causing these impls to overlap.
//
// However, we did fail to normalize `<Tensor as TensorValue::Unmasked`
// which caused the old solver to emit a `Tensor: TensorValue` goal in
// `fn normalize_to_error` which then failed, causing this test to pass.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass

pub trait TensorValue {
type Unmasked;
}

trait TensorCompare<T> {}
pub trait TensorOp<T>: TensorValue {}

pub struct Tensor;
impl<T2> TensorCompare<T2> for Tensor {}
impl<T1, T2> TensorCompare<T2> for T1
where
T1: TensorOp<T2>,
T1::Unmasked: Sized,
{}


fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
--> $DIR/super-trait-knowable-nested.rs:19:1
|
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
| ------------------------------------- first implementation here
LL | impl<T> Overlap<T> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: downstream crates may implement trait `Bound<_>` for type `()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
--> $DIR/super-trait-knowable-nested.rs:19:1
|
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
| ------------------------------------- first implementation here
LL | impl<T> Overlap<T> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: downstream crates may implement trait `Bound<_>` for type `()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
22 changes: 22 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-nested.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Unlike in `super-trait-knowable-1.rs`, the knowable
// super trait bound is in a nested goal and we currently
// only elaborate in the root. This can, and should, be#
// changed in the future.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

trait Super {}
trait Sub<T>: Super {}

trait Bound<T> {}

impl<T: Sub<T>, U> Bound<U> for T {}

trait Overlap<T> {}
impl<T, U: Bound<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}
//~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`

fn main() {}
7 changes: 6 additions & 1 deletion tests/ui/issues/issue-48728.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// Regression test for #48728, an ICE that occurred computing
// coherence "help" information.

#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone`
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass

#[derive(Clone)]
struct Node<T: ?Sized>(Box<T>);

impl<T: Clone + ?Sized> Clone for Node<[T]> {
4 changes: 2 additions & 2 deletions tests/ui/lifetimes/issue-34979.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ impl<'a, T> Foo for &'a T {}

struct Ctx<'a>(&'a ())
where
&'a (): Foo, //~ ERROR: type annotations needed
&'static (): Foo;
&'a (): Foo,
&'static (): Foo; //~ ERROR: mismatched types

fn main() {}
26 changes: 12 additions & 14 deletions tests/ui/lifetimes/issue-34979.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
--> $DIR/issue-34979.rs:6:13
error[E0308]: mismatched types
--> $DIR/issue-34979.rs:7:18
|
LL | &'a (): Foo,
| ^^^
LL | &'static (): Foo;
| ^^^ lifetime mismatch
|
note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
--> $DIR/issue-34979.rs:2:1
= note: expected trait `<&'static () as Foo>`
found trait `<&'a () as Foo>`
note: the lifetime `'a` as defined here...
--> $DIR/issue-34979.rs:4:12
|
LL | impl<'a, T> Foo for &'a T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | &'a (): Foo,
| ^^^
LL | &'static (): Foo;
| ^^^
LL | struct Ctx<'a>(&'a ())
| ^^
= note: ...does not necessarily outlive the static lifetime

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0283`.
For more information about this error, try `rustc --explain E0308`.
205 changes: 0 additions & 205 deletions tests/ui/traits/issue-66768.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/coherence-fulfill-overflow.rs:12:1
|
LL | impl<T: ?Sized + TwoW> Trait for W<T> {}
| ------------------------------------- first implementation here
LL | impl<T: ?Sized + TwoW> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
|
= note: overflow evaluating the requirement `W<W<W<W<W<_>>>>>: TwoW`
= note: overflow evaluating the requirement `W<W<W<W<_>>>>: TwoW`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`)

3 changes: 3 additions & 0 deletions tests/ui/traits/normalize-conflicting-impls.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// This is a mutated variant of #66768 which has been removed
// as it no longer tests the original issue.
fn problematic_function<Space>(material_surface_element: ())
where
DefaultAllocator: FiniteElementAllocator<(), Space>,
{
let _: Point2<f64> = material_surface_element.map_reference_coords().into();
//~^ ERROR the trait bound `Point<f64, u32>: From<Matrix<()>>` is not satisfied
}

impl<N, R> Allocator<N, R> for DefaultAllocator
18 changes: 14 additions & 4 deletions tests/ui/traits/normalize-conflicting-impls.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0220]: associated type `Value` not found for `R`
--> $DIR/normalize-conflicting-impls.rs:10:8
--> $DIR/normalize-conflicting-impls.rs:13:8
|
LL | R::Value: DimName,
| ^^^^^ associated type `Value` not found

error[E0119]: conflicting implementations of trait `Allocator<_, ()>` for type `DefaultAllocator`
--> $DIR/normalize-conflicting-impls.rs:14:1
--> $DIR/normalize-conflicting-impls.rs:17:1
|
LL | / impl<N, R> Allocator<N, R> for DefaultAllocator
LL | | where
@@ -15,7 +15,17 @@ LL | | R::Value: DimName,
LL | impl<N> Allocator<N, ()> for DefaultAllocator {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `DefaultAllocator`

error: aborting due to 2 previous errors
error[E0277]: the trait bound `Point<f64, u32>: From<Matrix<()>>` is not satisfied
--> $DIR/normalize-conflicting-impls.rs:7:74
|
LL | let _: Point2<f64> = material_surface_element.map_reference_coords().into();
| ^^^^ the trait `From<Matrix<()>>` is not implemented for `Point<f64, u32>`, which is required by `Matrix<()>: Into<_>`
|
= help: the trait `From<Matrix<<DefaultAllocator as Allocator<f64, u32>>::Buffer>>` is implemented for `Point<f64, u32>`
= help: for that trait implementation, expected `<DefaultAllocator as Allocator<f64, u32>>::Buffer`, found `()`
= note: required for `Matrix<()>` to implement `Into<Point<f64, u32>>`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0119, E0220.
Some errors have detailed explanations: E0119, E0220, E0277.
For more information about an error, try `rustc --explain E0119`.