Skip to content

Commit 2c1c008

Browse files
authored
Unrolled build for rust-lang#139789
Rollup merge of rust-lang#139789 - lcnr:opaques-auto-trait-leakage, r=compiler-errors do not unnecessarily leak auto traits in item bounds fixes rust-lang/trait-system-refactor-initiative#158 Not a fix for rust-lang/trait-system-refactor-initiative#173 as you may have realized/tried yourself, cc rust-lang#139788. However, fixing this feels desirable regardless and I don't see any reason not to. r? ```@compiler-errors```
2 parents 58c2dd9 + 836ea25 commit 2c1c008

16 files changed

+285
-7
lines changed

Diff for: compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ where
164164
ecx: &mut EvalCtxt<'_, D>,
165165
goal: Goal<I, Self>,
166166
) -> Result<Candidate<I>, NoSolution> {
167+
let cx = ecx.cx();
167168
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
168169
return Err(NoSolution);
169170
}
@@ -174,20 +175,37 @@ where
174175

175176
// Only consider auto impls of unsafe traits when there are no unsafe
176177
// fields.
177-
if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
178+
if cx.trait_is_unsafe(goal.predicate.def_id())
178179
&& goal.predicate.self_ty().has_unsafe_fields()
179180
{
180181
return Err(NoSolution);
181182
}
182183

183-
// We only look into opaque types during analysis for opaque types
184-
// outside of their defining scope. Doing so for opaques in the
185-
// defining scope may require calling `typeck` on the same item we're
186-
// currently type checking, which will result in a fatal cycle that
187-
// ideally we want to avoid, since we can make progress on this goal
188-
// via an alias bound or a locally-inferred hidden type instead.
184+
// We leak the implemented auto traits of opaques outside of their defining scope.
185+
// This depends on `typeck` of the defining scope of that opaque, which may result in
186+
// fatal query cycles.
187+
//
188+
// We only get to this point if we're outside of the defining scope as we'd otherwise
189+
// be able to normalize the opaque type. We may also cycle in case `typeck` of a defining
190+
// scope relies on the current context, e.g. either because it also leaks auto trait
191+
// bounds of opaques defined in the current context or by evaluating the current item.
192+
//
193+
// To avoid this we don't try to leak auto trait bounds if they can also be proven via
194+
// item bounds of the opaque. These bounds are always applicable as auto traits must not
195+
// have any generic parameters. They would also get preferred over the impl candidate
196+
// when merging candidates anyways.
197+
//
198+
// See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs.
189199
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
190200
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
201+
for item_bound in cx.item_self_bounds(opaque_ty.def_id).skip_binder() {
202+
if item_bound
203+
.as_trait_clause()
204+
.is_some_and(|b| b.def_id() == goal.predicate.def_id())
205+
{
206+
return Err(NoSolution);
207+
}
208+
}
191209
}
192210

193211
ecx.probe_and_evaluate_goal_for_constituent_tys(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
5+
6+
// When proving auto trait bounds, make sure that we depend on auto trait
7+
// leakage if we can also prove it via an item bound.
8+
fn is_send<T: Send>(_: T) {}
9+
10+
fn direct() -> impl Send {
11+
is_send(check(false)); // leaks auto traits, depends on `check`
12+
1u16
13+
}
14+
15+
trait Indir: Send {}
16+
impl Indir for u32 {}
17+
fn indir() -> impl Indir {
18+
is_send(check(false)); // leaks auto traits, depends on `check`
19+
1u32
20+
}
21+
22+
fn check(b: bool) -> impl Sized {
23+
if b {
24+
// must not leak auto traits, as we otherwise get a query cycle.
25+
is_send(direct());
26+
is_send(indir());
27+
}
28+
1u64
29+
}
30+
31+
fn main() {
32+
check(true);
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
2+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
3+
|
4+
LL | fn foo(b: bool) -> impl Sized {
5+
| ^^^^^^^^^^
6+
|
7+
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
8+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
9+
|
10+
LL | fn foo(b: bool) -> impl Sized {
11+
| ^^^^^^^^^^
12+
= note: ...which requires evaluating trait selection obligation `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}: core::marker::Send`...
13+
note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
14+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
15+
|
16+
LL | fn foo(b: bool) -> impl Sized {
17+
| ^^^^^^^^^^
18+
note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
19+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
20+
|
21+
LL | fn foo(b: bool) -> impl Sized {
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
24+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
25+
|
26+
LL | fn foo(b: bool) -> impl Sized {
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
29+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
30+
|
31+
LL | fn foo(b: bool) -> impl Sized {
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33+
note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
34+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
35+
|
36+
LL | fn foo(b: bool) -> impl Sized {
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
39+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
40+
|
41+
LL | fn foo(b: bool) -> impl Sized {
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43+
note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
44+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
45+
|
46+
LL | fn foo(b: bool) -> impl Sized {
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
49+
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
50+
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
51+
|
52+
LL | impl Trait for u32 {
53+
| ^^^^^^^^^^^^^^^^^^
54+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
55+
56+
error: aborting due to 1 previous error
57+
58+
For more information about this error, try `rustc --explain E0391`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
2+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
3+
|
4+
LL | fn foo(b: bool) -> impl Sized {
5+
| ^^^^^^^^^^
6+
|
7+
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
8+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
9+
|
10+
LL | fn foo(b: bool) -> impl Sized {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
note: ...which requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
13+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
14+
|
15+
LL | fn foo(b: bool) -> impl Sized {
16+
| ^^^^^^^^^^
17+
note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
18+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
19+
|
20+
LL | fn foo(b: bool) -> impl Sized {
21+
| ^^^^^^^^^^
22+
note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
23+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
24+
|
25+
LL | fn foo(b: bool) -> impl Sized {
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
28+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
29+
|
30+
LL | fn foo(b: bool) -> impl Sized {
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
33+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
34+
|
35+
LL | fn foo(b: bool) -> impl Sized {
36+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37+
note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
38+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
39+
|
40+
LL | fn foo(b: bool) -> impl Sized {
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
43+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
44+
|
45+
LL | fn foo(b: bool) -> impl Sized {
46+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
48+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
49+
|
50+
LL | fn foo(b: bool) -> impl Sized {
51+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
53+
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
54+
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
55+
|
56+
LL | impl Trait for u32 {
57+
| ^^^^^^^^^^^^^^^^^^
58+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
59+
60+
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
61+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
62+
|
63+
LL | fn foo(b: bool) -> impl Sized {
64+
| ^^^^^^^^^^
65+
|
66+
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
67+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
68+
|
69+
LL | fn foo(b: bool) -> impl Sized {
70+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71+
note: ...which requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
72+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
73+
|
74+
LL | fn foo(b: bool) -> impl Sized {
75+
| ^^^^^^^^^^
76+
note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
77+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
78+
|
79+
LL | fn foo(b: bool) -> impl Sized {
80+
| ^^^^^^^^^^
81+
note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
82+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
83+
|
84+
LL | fn foo(b: bool) -> impl Sized {
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86+
note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
87+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
88+
|
89+
LL | fn foo(b: bool) -> impl Sized {
90+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
91+
note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
92+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
93+
|
94+
LL | fn foo(b: bool) -> impl Sized {
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96+
note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
97+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
98+
|
99+
LL | fn foo(b: bool) -> impl Sized {
100+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
101+
note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
102+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
103+
|
104+
LL | fn foo(b: bool) -> impl Sized {
105+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
106+
note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
107+
--> $DIR/method-compatability-via-leakage-cycle.rs:21:5
108+
|
109+
LL | fn foo(b: bool) -> impl Sized {
110+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111+
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
112+
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
113+
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
114+
|
115+
LL | impl Trait for u32 {
116+
| ^^^^^^^^^^^^^^^^^^
117+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
118+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
119+
120+
error: aborting due to 2 previous errors
121+
122+
For more information about this error, try `rustc --explain E0391`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@ known-bug: #139788
5+
6+
// Recursively using the trait method inside of an impl in case checking
7+
// method compatability relies on opaque type leakage currently causes a
8+
// cycle error.
9+
10+
trait Trait {
11+
// desugars to
12+
// type Assoc: Sized + Send;
13+
// fn foo(b: bool) -> Self::Assoc;
14+
fn foo(b: bool) -> impl Sized + Send;
15+
}
16+
17+
impl Trait for u32 {
18+
// desugars to
19+
// type Assoc = impl_rpit::<Self>;
20+
// fn foo(b: bool) -> Self::Assoc { .. }
21+
fn foo(b: bool) -> impl Sized {
22+
if b {
23+
u32::foo(false)
24+
} else {
25+
1u32
26+
}
27+
}
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
5+
6+
trait Trait {
7+
fn foo() -> impl Sized + Send;
8+
}
9+
10+
impl Trait for u32 {
11+
fn foo() -> impl Sized {}
12+
}
13+
14+
fn main() {}

Diff for: tests/ui/impl-trait/in-trait/refine-cycle.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
//@ check-pass
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
25

36
// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve`
47
// which calls `compare_impl_item`.

0 commit comments

Comments
 (0)