Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2466b92

Browse files
committedMay 1, 2024
Auto merge of #124592 - lcnr:winnowing-xd, r=<try>
cleaning `candidate_should_be_dropped_in_favor_of` and make sure it's actually a partial ordering :< - non-global where-bounds are preferred over impls - impls are preferred over global where-bound - non-global where-bounds and global where-bounds are considered equal The new solver currently does not implement thelowered priority of global `ParamEnv` candidates, so the divergence between it and the old solver in the added tests will be resolved in favor of the old solver behavior after this PR. r? `@compiler-errors`
2 parents 9ba3d31 + a0359c8 commit 2466b92

21 files changed

+278
-388
lines changed
 

‎compiler/rustc_middle/src/traits/select.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,18 @@ pub enum SelectionCandidate<'tcx> {
121121
/// Implementation of transmutability trait.
122122
TransmutabilityCandidate,
123123

124-
ParamCandidate(ty::PolyTraitPredicate<'tcx>),
124+
/// A candidate from the `ParamEnv`.
125+
ParamCandidate {
126+
/// The actual `where`-bound, e.g. `T: Trait`.
127+
predicate: ty::PolyTraitPredicate<'tcx>,
128+
/// `true` if the where-bound has no bound vars and does
129+
/// not refer to any parameters or inference variables.
130+
///
131+
/// We prefer all other candidates over global where-bounds.
132+
/// Notably, global where-bounds do not shadow impls.
133+
is_global: bool,
134+
},
135+
125136
ImplCandidate(DefId),
126137
AutoImplCandidate,
127138

‎compiler/rustc_trait_selection/src/traits/coherence.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -792,11 +792,8 @@ pub fn orphan_check_trait_ref<'tcx, E: Debug>(
792792
in_crate: InCrate,
793793
lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
794794
) -> Result<Result<(), OrphanCheckErr<'tcx, Ty<'tcx>>>, E> {
795-
if trait_ref.has_infer() && trait_ref.has_param() {
796-
bug!(
797-
"can't orphan check a trait ref with both params and inference variables {:?}",
798-
trait_ref
799-
);
795+
if trait_ref.has_param() {
796+
bug!("orphan check only expects inference variables: {trait_ref:?}");
800797
}
801798

802799
let mut checker = OrphanChecker::new(in_crate, lazily_normalize_ty);

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -251,16 +251,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
251251
all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
252252

253253
// Keep only those bounds which may apply, and propagate overflow if it occurs.
254-
for bound in matching_bounds {
255-
if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity {
254+
for predicate in matching_bounds {
255+
if predicate.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity
256+
{
256257
continue;
257258
}
258259

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

‎compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
5656
ImplSource::Builtin(BuiltinImplSource::Misc, data)
5757
}
5858

59-
ParamCandidate(param) => {
59+
ParamCandidate { predicate, is_global: _ } => {
6060
let obligations =
61-
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
61+
self.confirm_param_candidate(obligation, predicate.map_bound(|t| t.trait_ref));
6262
ImplSource::Param(obligations)
6363
}
6464

‎compiler/rustc_trait_selection/src/traits/select/mod.rs

+44-148
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15751575
return false;
15761576
}
15771577
match result {
1578-
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
1578+
Ok(Some(SelectionCandidate::ParamCandidate { predicate, .. })) => {
1579+
!predicate.has_infer()
1580+
}
15791581
_ => true,
15801582
}
15811583
}
@@ -1827,31 +1829,35 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18271829
return DropVictim::Yes;
18281830
}
18291831

1830-
// Check if a bound would previously have been removed when normalizing
1831-
// the param_env so that it can be given the lowest priority. See
1832-
// #50825 for the motivation for this.
1833-
let is_global =
1834-
|cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
1835-
1836-
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
1837-
// `DiscriminantKindCandidate`, `ConstDestructCandidate`
1838-
// to anything else.
1839-
//
1840-
// This is a fix for #53123 and prevents winnowing from accidentally extending the
1841-
// lifetime of a variable.
18421832
match (&other.candidate, &victim.candidate) {
1843-
// FIXME(@jswrenn): this should probably be more sophisticated
1844-
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
1845-
1846-
// (*)
1833+
// Prefer `BuiltinCandidate { has_nested: false }`, `ConstDestructCandidate`
1834+
// to anything else.
1835+
//
1836+
// This is a fix for #53123 and prevents winnowing from accidentally extending the
1837+
// lifetime of a variable.
1838+
(
1839+
BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_),
1840+
BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_),
1841+
) => bug!("two trivial builtin candidates: {other:?} {victim:?}"),
18471842
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
18481843
DropVictim::Yes
18491844
}
18501845
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
18511846
DropVictim::No
18521847
}
18531848

1854-
(ParamCandidate(other), ParamCandidate(victim)) => {
1849+
// Global bounds from the where clause should be ignored
1850+
// here (see issue #50825).
1851+
(ParamCandidate { is_global: true, .. }, ParamCandidate { is_global: true, .. }) => {
1852+
DropVictim::No
1853+
}
1854+
(_, ParamCandidate { is_global: true, .. }) => DropVictim::Yes,
1855+
(ParamCandidate { is_global: true, .. }, _) => DropVictim::No,
1856+
1857+
(
1858+
ParamCandidate { is_global: false, predicate: other },
1859+
ParamCandidate { is_global: false, predicate: victim },
1860+
) => {
18551861
let same_except_bound_vars = other.skip_binder().trait_ref
18561862
== victim.skip_binder().trait_ref
18571863
&& other.skip_binder().polarity == victim.skip_binder().polarity
@@ -1868,68 +1874,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18681874
}
18691875
}
18701876

1871-
// Drop otherwise equivalent non-const fn pointer candidates
1872-
(FnPointerCandidate { .. }, FnPointerCandidate { fn_host_effect }) => {
1873-
DropVictim::drop_if(*fn_host_effect == self.tcx().consts.true_)
1874-
}
1875-
1876-
(
1877-
ParamCandidate(ref other_cand),
1878-
ImplCandidate(..)
1879-
| AutoImplCandidate
1880-
| ClosureCandidate { .. }
1881-
| AsyncClosureCandidate
1882-
| AsyncFnKindHelperCandidate
1883-
| CoroutineCandidate
1884-
| FutureCandidate
1885-
| IteratorCandidate
1886-
| AsyncIteratorCandidate
1887-
| FnPointerCandidate { .. }
1888-
| BuiltinObjectCandidate
1889-
| BuiltinUnsizeCandidate
1890-
| TraitUpcastingUnsizeCandidate(_)
1891-
| BuiltinCandidate { .. }
1892-
| TraitAliasCandidate
1893-
| ObjectCandidate(_)
1894-
| ProjectionCandidate(_),
1895-
) => {
1896-
// We have a where clause so don't go around looking
1897-
// for impls. Arbitrarily give param candidates priority
1898-
// over projection and object candidates.
1899-
//
1900-
// Global bounds from the where clause should be ignored
1901-
// here (see issue #50825).
1902-
DropVictim::drop_if(!is_global(other_cand))
1903-
}
1904-
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
1905-
// Prefer these to a global where-clause bound
1906-
// (see issue #50825).
1907-
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
1908-
}
1909-
(
1910-
ImplCandidate(_)
1911-
| AutoImplCandidate
1912-
| ClosureCandidate { .. }
1913-
| AsyncClosureCandidate
1914-
| AsyncFnKindHelperCandidate
1915-
| CoroutineCandidate
1916-
| FutureCandidate
1917-
| IteratorCandidate
1918-
| AsyncIteratorCandidate
1919-
| FnPointerCandidate { .. }
1920-
| BuiltinObjectCandidate
1921-
| BuiltinUnsizeCandidate
1922-
| TraitUpcastingUnsizeCandidate(_)
1923-
| BuiltinCandidate { has_nested: true }
1924-
| TraitAliasCandidate,
1925-
ParamCandidate(ref victim_cand),
1926-
) => {
1927-
// Prefer these to a global where-clause bound
1928-
// (see issue #50825).
1929-
DropVictim::drop_if(
1930-
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(),
1931-
)
1932-
}
1877+
(ParamCandidate { is_global: false, .. }, _) => DropVictim::Yes,
1878+
(_, ParamCandidate { is_global: false, .. }) => DropVictim::No,
19331879

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

1945-
// Arbitrarily give projection and object candidates priority.
1946-
(
1947-
ObjectCandidate(_) | ProjectionCandidate(_),
1948-
ImplCandidate(..)
1949-
| AutoImplCandidate
1950-
| ClosureCandidate { .. }
1951-
| AsyncClosureCandidate
1952-
| AsyncFnKindHelperCandidate
1953-
| CoroutineCandidate
1954-
| FutureCandidate
1955-
| IteratorCandidate
1956-
| AsyncIteratorCandidate
1957-
| FnPointerCandidate { .. }
1958-
| BuiltinObjectCandidate
1959-
| BuiltinUnsizeCandidate
1960-
| TraitUpcastingUnsizeCandidate(_)
1961-
| BuiltinCandidate { .. }
1962-
| TraitAliasCandidate,
1963-
) => DropVictim::Yes,
1891+
// Arbitrarily give projection candidates priority.
1892+
(ProjectionCandidate(_), _) => DropVictim::Yes,
1893+
(_, ProjectionCandidate(_)) => DropVictim::No,
19641894

1965-
(
1966-
ImplCandidate(..)
1967-
| AutoImplCandidate
1968-
| ClosureCandidate { .. }
1969-
| AsyncClosureCandidate
1970-
| AsyncFnKindHelperCandidate
1971-
| CoroutineCandidate
1972-
| FutureCandidate
1973-
| IteratorCandidate
1974-
| AsyncIteratorCandidate
1975-
| FnPointerCandidate { .. }
1976-
| BuiltinObjectCandidate
1977-
| BuiltinUnsizeCandidate
1978-
| TraitUpcastingUnsizeCandidate(_)
1979-
| BuiltinCandidate { .. }
1980-
| TraitAliasCandidate,
1981-
ObjectCandidate(_) | ProjectionCandidate(_),
1982-
) => DropVictim::No,
1895+
// Need to prioritize builtin trait object impls as
1896+
// `<dyn Any as Any>::type_id` should use the vtable method
1897+
// and not the method provided by the user-defined impl
1898+
// `impl<T: ?Sized> Any for T { .. }`.
1899+
//
1900+
// cc #57893
1901+
(ObjectCandidate(_), _) => DropVictim::Yes,
1902+
(_, ObjectCandidate(_)) => DropVictim::No,
19831903

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

2062-
(AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => {
2063-
DropVictim::No
2064-
}
2065-
2066-
(AutoImplCandidate, _) | (_, AutoImplCandidate) => {
2067-
bug!(
2068-
"default implementations shouldn't be recorded \
2069-
when there are other global candidates: {:?} {:?}",
2070-
other,
2071-
victim
2072-
);
2073-
}
2074-
2075-
// Everything else is ambiguous
1982+
// Treat all non-trivial builtin impls and user-defined impls the same way.
20761983
(
20771984
ImplCandidate(_)
2078-
| ClosureCandidate { .. }
2079-
| AsyncClosureCandidate
2080-
| AsyncFnKindHelperCandidate
2081-
| CoroutineCandidate
2082-
| FutureCandidate
2083-
| IteratorCandidate
2084-
| AsyncIteratorCandidate
2085-
| FnPointerCandidate { .. }
2086-
| BuiltinObjectCandidate
2087-
| BuiltinUnsizeCandidate
2088-
| TraitUpcastingUnsizeCandidate(_)
1985+
| AutoImplCandidate
20891986
| BuiltinCandidate { has_nested: true }
2090-
| TraitAliasCandidate,
2091-
ImplCandidate(_)
2092-
| ClosureCandidate { .. }
20931987
| AsyncClosureCandidate
20941988
| AsyncFnKindHelperCandidate
20951989
| CoroutineCandidate
20961990
| FutureCandidate
20971991
| IteratorCandidate
20981992
| AsyncIteratorCandidate
20991993
| FnPointerCandidate { .. }
2100-
| BuiltinObjectCandidate
1994+
| ClosureCandidate { .. }
1995+
| TraitAliasCandidate
21011996
| BuiltinUnsizeCandidate
21021997
| TraitUpcastingUnsizeCandidate(_)
2103-
| BuiltinCandidate { has_nested: true }
2104-
| TraitAliasCandidate,
1998+
| TransmutabilityCandidate
1999+
| BuiltinObjectCandidate,
2000+
_,
21052001
) => DropVictim::No,
21062002
}
21072003
}

‎src/tools/tidy/src/issues.txt

-1
Original file line numberDiff line numberDiff line change
@@ -4062,7 +4062,6 @@ ui/traits/issue-6128.rs
40624062
ui/traits/issue-6334.rs
40634063
ui/traits/issue-65284-suggest-generic-trait-bound.rs
40644064
ui/traits/issue-65673.rs
4065-
ui/traits/issue-66768.rs
40664065
ui/traits/issue-68295.rs
40674066
ui/traits/issue-7013.rs
40684067
ui/traits/issue-70944.rs

‎tests/ui/associated-item/issue-105449.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
//@ check-pass
21
//@ compile-flags: -C debug_assertions=yes -Zunstable-options
32

4-
#[allow(dead_code)]
3+
// This is a mutated variant of #66768 which has been removed
4+
// as it no longer tests the original issue.
55
fn problematic_function<Space>()
66
where
77
DefaultAlloc: FinAllok<R1, Space>,
88
{
99
let e = Edge2dElement;
1010
let _ = Into::<Point>::into(e.map_reference_coords());
11+
//~^ ERROR the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied
1112
}
1213
impl<N> Allocator<N, R0> for DefaultAlloc {
1314
type Buffer = MStorage;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied
2+
--> $DIR/issue-105449.rs:10:33
3+
|
4+
LL | let _ = Into::<Point>::into(e.map_reference_coords());
5+
| ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<(Ure, R1, MStorage)>` is not implemented for `Point`, which is required by `(Ure, R1, MStorage): Into<Point>`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `From<(Ure, Space, <DefaultAlloc as Allocator<Ure, Space>>::Buffer)>` is implemented for `Point`
10+
= help: for that trait implementation, expected `Space`, found `R1`
11+
= note: required for `(Ure, R1, MStorage)` to implement `Into<Point>`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.

‎tests/ui/lifetimes/issue-34979.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ impl<'a, T> Foo for &'a T {}
33

44
struct Ctx<'a>(&'a ())
55
where
6-
&'a (): Foo, //~ ERROR: type annotations needed
7-
&'static (): Foo;
6+
&'a (): Foo,
7+
&'static (): Foo; //~ ERROR: mismatched types
88

99
fn main() {}

‎tests/ui/lifetimes/issue-34979.stderr

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
2-
--> $DIR/issue-34979.rs:6:13
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-34979.rs:7:18
33
|
4-
LL | &'a (): Foo,
5-
| ^^^
4+
LL | &'static (): Foo;
5+
| ^^^ lifetime mismatch
66
|
7-
note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
8-
--> $DIR/issue-34979.rs:2:1
7+
= note: expected trait `<&'static () as Foo>`
8+
found trait `<&'a () as Foo>`
9+
note: the lifetime `'a` as defined here...
10+
--> $DIR/issue-34979.rs:4:12
911
|
10-
LL | impl<'a, T> Foo for &'a T {}
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12-
...
13-
LL | &'a (): Foo,
14-
| ^^^
15-
LL | &'static (): Foo;
16-
| ^^^
12+
LL | struct Ctx<'a>(&'a ())
13+
| ^^
14+
= note: ...does not necessarily outlive the static lifetime
1715

1816
error: aborting due to 1 previous error
1917

20-
For more information about this error, try `rustc --explain E0283`.
18+
For more information about this error, try `rustc --explain E0308`.

‎tests/ui/traits/issue-66768.rs

-205
This file was deleted.

‎tests/ui/traits/normalize-conflicting-impls.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
// This is a mutated variant of #66768 which has been removed
2+
// as it no longer tests the original issue.
13
fn problematic_function<Space>(material_surface_element: ())
24
where
35
DefaultAllocator: FiniteElementAllocator<(), Space>,
46
{
57
let _: Point2<f64> = material_surface_element.map_reference_coords().into();
8+
//~^ ERROR the trait bound `Point<f64, u32>: From<Matrix<()>>` is not satisfied
69
}
710

811
impl<N, R> Allocator<N, R> for DefaultAllocator
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0220]: associated type `Value` not found for `R`
2-
--> $DIR/normalize-conflicting-impls.rs:10:8
2+
--> $DIR/normalize-conflicting-impls.rs:13:8
33
|
44
LL | R::Value: DimName,
55
| ^^^^^ associated type `Value` not found
66

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

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

20-
Some errors have detailed explanations: E0119, E0220.
30+
Some errors have detailed explanations: E0119, E0220, E0277.
2131
For more information about an error, try `rustc --explain E0119`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/global-non-global-env-1.rs:18:5
3+
|
4+
LL | fn foo<T>() -> u32
5+
| - --- expected `u32` because of return type
6+
| |
7+
| found this type parameter
8+
...
9+
LL | impls_trait(())
10+
| ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
11+
|
12+
= note: expected type `u32`
13+
found type parameter `T`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// A regression test for an edge case of candidate selection
2+
// in the old trait solver, see #124592 for more details.
3+
4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
//@[next] check-pass
8+
9+
trait Trait<T> {}
10+
impl<T> Trait<T> for () {}
11+
12+
fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
13+
fn foo<T>() -> u32
14+
where
15+
(): Trait<u32>,
16+
(): Trait<T>,
17+
{
18+
impls_trait(())
19+
//[current]~^ ERROR mismatched types
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/global-non-global-env-2.rs:20:5
3+
|
4+
LL | fn foo<T>() -> u32
5+
| - --- expected `u32` because of return type
6+
| |
7+
| found this type parameter
8+
...
9+
LL | impls_trait(())
10+
| ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
11+
|
12+
= note: expected type `u32`
13+
found type parameter `T`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// A regression test for an edge case of candidate selection
2+
// in the old trait solver, see #124592 for more details. Unlike
3+
// the first test, this one has two impl candidates.
4+
5+
//@ revisions: current next
6+
//@ ignore-compare-mode-next-solver (explicit revisions)
7+
//@[next] compile-flags: -Znext-solver
8+
//@[next] check-pass
9+
10+
trait Trait<T> {}
11+
impl Trait<u32> for () {}
12+
impl Trait<u64> for () {}
13+
14+
fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
15+
fn foo<T>() -> u32
16+
where
17+
(): Trait<u32>,
18+
(): Trait<T>,
19+
{
20+
impls_trait(())
21+
//[current]~^ ERROR mismatched types
22+
}
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/global-non-global-env-3.rs:20:5
3+
|
4+
LL | fn foo<T>() -> u32
5+
| - --- expected `u32` because of return type
6+
| |
7+
| found this type parameter
8+
...
9+
LL | impls_trait(())
10+
| ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
11+
|
12+
= note: expected type `u32`
13+
found type parameter `T`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// A regression test for an edge case of candidate selection
2+
// in the old trait solver, see #124592 for more details. Unlike
3+
// the second test, the where-bounds are in a different order.
4+
5+
//@ revisions: current next
6+
//@ ignore-compare-mode-next-solver (explicit revisions)
7+
//@[next] compile-flags: -Znext-solver
8+
//@[next] check-pass
9+
10+
trait Trait<T> {}
11+
impl Trait<u32> for () {}
12+
impl Trait<u64> for () {}
13+
14+
fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
15+
fn foo<T>() -> u32
16+
where
17+
(): Trait<T>,
18+
(): Trait<u32>,
19+
{
20+
impls_trait(())
21+
//[current]~^ ERROR mismatched types
22+
}
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/global-non-global-env-4.rs:21:5
3+
|
4+
LL | fn foo<T>() -> u32
5+
| - --- expected `u32` because of return type
6+
| |
7+
| found this type parameter
8+
...
9+
LL | impls_trait(())
10+
| ^^^^^^^^^^^^^^^ expected `u32`, found type parameter `T`
11+
|
12+
= note: expected type `u32`
13+
found type parameter `T`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// A regression test for an edge case of candidate selection
2+
// in the old trait solver, see #124592 for more details. Unlike
3+
// the third test, this one has 3 impl candidates.
4+
5+
//@ revisions: current next
6+
//@ ignore-compare-mode-next-solver (explicit revisions)
7+
//@[next] compile-flags: -Znext-solver
8+
//@[next] check-pass
9+
10+
trait Trait<T> {}
11+
impl Trait<u32> for () {}
12+
impl Trait<u64> for () {}
13+
impl Trait<u128> for () {}
14+
15+
fn impls_trait<T: Trait<U>, U>(_: T) -> U { todo!() }
16+
fn foo<T>() -> u32
17+
where
18+
(): Trait<T>,
19+
(): Trait<u32>,
20+
{
21+
impls_trait(())
22+
//[current]~^ ERROR mismatched types
23+
}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.