Skip to content
/ rust Public
forked from rust-lang/rust

Commit 3adedc9

Browse files
lcnrDdystopia
authored andcommitted
update auto trait handling
1 parent b112bc5 commit 3adedc9

11 files changed

+339
-78
lines changed

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

+45-7
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
124124

125125
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
126126
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
127-
// Auto implementations have lower priority, so we only
128-
// consider triggering a default if there is no other impl that can apply.
129-
if candidates.vec.is_empty() {
130-
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
131-
}
127+
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
132128
}
133129
debug!("candidate list size: {}", candidates.vec.len());
134130
Ok(candidates)
@@ -516,7 +512,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
516512
// for an example of a test case that exercises
517513
// this path.
518514
}
519-
ty::Infer(ty::TyVar(_)) => {
515+
ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
520516
// The auto impl might apply; we don't know.
521517
candidates.ambiguous = true;
522518
}
@@ -536,7 +532,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
536532
}
537533
}
538534

539-
_ => candidates.vec.push(AutoImplCandidate),
535+
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
536+
bug!(
537+
"asked to assemble auto trait candidates of unexpected type: {:?}",
538+
self_ty
539+
);
540+
}
541+
542+
// Only consider auto impls if there are no manual impls for the root of `self_ty`.
543+
//
544+
// For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
545+
// for `&SomeType: Auto` exists. Due to E0321 the only crate where impls
546+
// for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined.
547+
//
548+
// Generally, we have to guarantee that for all `SimplifiedType`s the only crate
549+
// which may define impls for that type is either the crate defining the type
550+
// or the trait. This should be guaranteed by the orphan check.
551+
ty::Bool
552+
| ty::Char
553+
| ty::Int(_)
554+
| ty::Uint(_)
555+
| ty::Float(_)
556+
| ty::Str
557+
| ty::Array(_, _)
558+
| ty::Slice(_)
559+
| ty::Adt(..)
560+
| ty::RawPtr(_)
561+
| ty::Ref(..)
562+
| ty::FnDef(..)
563+
| ty::FnPtr(_)
564+
| ty::Closure(_, _)
565+
| ty::Generator(..)
566+
| ty::Never
567+
| ty::Tuple(_)
568+
| ty::Alias(_, _)
569+
| ty::GeneratorWitness(_)
570+
| ty::GeneratorWitnessMIR(..) => {
571+
let mut has_impl = false;
572+
self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
573+
if !has_impl {
574+
candidates.vec.push(AutoImplCandidate)
575+
}
576+
}
577+
ty::Error(_) => {} // do not add an auto trait impl for `ty::Error` for now.
540578
}
541579
}
542580
}

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

+18-7
Original file line numberDiff line numberDiff line change
@@ -1814,6 +1814,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18141814
/// candidates and prefer where-clause candidates.
18151815
///
18161816
/// See the comment for "SelectionCandidate" for more details.
1817+
#[instrument(level = "debug", skip(self))]
18171818
fn candidate_should_be_dropped_in_favor_of(
18181819
&mut self,
18191820
victim: &EvaluatedCandidate<'tcx>,
@@ -1837,13 +1838,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18371838
// This is a fix for #53123 and prevents winnowing from accidentally extending the
18381839
// lifetime of a variable.
18391840
match (&other.candidate, &victim.candidate) {
1840-
(_, AutoImplCandidate) | (AutoImplCandidate, _) => {
1841-
bug!(
1842-
"default implementations shouldn't be recorded \
1843-
when there are other valid candidates"
1844-
);
1845-
}
1846-
18471841
// FIXME(@jswrenn): this should probably be more sophisticated
18481842
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
18491843

@@ -1885,6 +1879,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18851879
(
18861880
ParamCandidate(ref other_cand),
18871881
ImplCandidate(..)
1882+
| AutoImplCandidate
18881883
| ClosureCandidate { .. }
18891884
| GeneratorCandidate
18901885
| FutureCandidate
@@ -1912,6 +1907,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19121907
}
19131908
(
19141909
ImplCandidate(_)
1910+
| AutoImplCandidate
19151911
| ClosureCandidate { .. }
19161912
| GeneratorCandidate
19171913
| FutureCandidate
@@ -1945,6 +1941,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19451941
(
19461942
ObjectCandidate(_) | ProjectionCandidate(..),
19471943
ImplCandidate(..)
1944+
| AutoImplCandidate
19481945
| ClosureCandidate { .. }
19491946
| GeneratorCandidate
19501947
| FutureCandidate
@@ -1958,6 +1955,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19581955

19591956
(
19601957
ImplCandidate(..)
1958+
| AutoImplCandidate
19611959
| ClosureCandidate { .. }
19621960
| GeneratorCandidate
19631961
| FutureCandidate
@@ -2048,6 +2046,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
20482046
}
20492047
}
20502048

2049+
(AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => {
2050+
DropVictim::No
2051+
}
2052+
2053+
(AutoImplCandidate, _) | (_, AutoImplCandidate) => {
2054+
bug!(
2055+
"default implementations shouldn't be recorded \
2056+
when there are other global candidates: {:?} {:?}",
2057+
other,
2058+
victim
2059+
);
2060+
}
2061+
20512062
// Everything else is ambiguous
20522063
(
20532064
ImplCandidate(_)
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![allow(suspicious_auto_trait_impls)]
2+
3+
struct Always<T, U>(T, U);
4+
unsafe impl<T, U> Send for Always<T, U> {}
5+
struct Foo<T, U>(Always<T, U>);
6+
7+
trait False {}
8+
unsafe impl<U: False> Send for Foo<u32, U> {}
9+
10+
trait WithAssoc {
11+
type Output;
12+
}
13+
impl<T: Send> WithAssoc for T {
14+
type Output = Self;
15+
}
16+
impl WithAssoc for Foo<u32, ()> {
17+
type Output = Box<i32>;
18+
}
19+
20+
fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
21+
//~^ ERROR `Foo<T, U>` cannot be sent between threads safely
22+
f(foo(v));
23+
}
24+
25+
fn foo<T: Send>(x: T) -> <T as WithAssoc>::Output {
26+
x
27+
}
28+
29+
fn main() {
30+
generic(Foo(Always(0, ())), |b| *b);
31+
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: `Foo<T, U>` cannot be sent between threads safely
2+
--> $DIR/issue-83857-ub.rs:20:38
3+
|
4+
LL | fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo<T, U>` cannot be sent between threads safely
6+
|
7+
= help: the trait `Send` is not implemented for `Foo<T, U>`
8+
note: required for `Foo<T, U>` to implement `WithAssoc`
9+
--> $DIR/issue-83857-ub.rs:13:15
10+
|
11+
LL | impl<T: Send> WithAssoc for T {
12+
| ---- ^^^^^^^^^ ^
13+
| |
14+
| unsatisfied trait bound introduced here
15+
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
16+
|
17+
LL | fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) where Foo<T, U>: Send {
18+
| +++++++++++++++++++++
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.

tests/ui/generator/auto-trait-regions.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn assert_foo<T: Foo>(f: T) {}
2626
fn main() {
2727
// Make sure 'static is erased for generator interiors so we can't match it in trait selection
2828
let x: &'static _ = &OnlyFooIfStaticRef(No);
29-
let gen = || {
29+
let gen = move || {
3030
let x = x;
3131
yield;
3232
assert_foo(x);
@@ -36,15 +36,15 @@ fn main() {
3636

3737
// Allow impls which matches any lifetime
3838
let x = &OnlyFooIfRef(No);
39-
let gen = || {
39+
let gen = move || {
4040
let x = x;
4141
yield;
4242
assert_foo(x);
4343
};
4444
assert_foo(gen); // ok
4545

4646
// Disallow impls which relates lifetimes in the generator interior
47-
let gen = || {
47+
let gen = move || {
4848
let a = A(&mut true, &mut true, No);
4949
//~^ temporary value dropped while borrowed
5050
//~| temporary value dropped while borrowed

tests/ui/impl-trait/auto-trait-leak

Whitespace-only changes.

tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr

+22-20
Original file line numberDiff line numberDiff line change
@@ -123,30 +123,32 @@ LL | | x;
123123
LL | | }
124124
| |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
125125

126-
error[E0720]: cannot resolve opaque type
126+
error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
127127
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
128128
|
129129
LL | fn mutual_recursion() -> impl Sync {
130-
| ^^^^^^^^^ recursive opaque type
131-
LL |
132-
LL | mutual_recursion_b()
133-
| -------------------- returning here with type `impl Sized`
134-
...
135-
LL | fn mutual_recursion_b() -> impl Sized {
136-
| ---------- returning this opaque type `impl Sized`
137-
138-
error[E0720]: cannot resolve opaque type
139-
--> $DIR/recursive-impl-trait-type-indirect.rs:95:28
130+
| ^^^^^^^^^
131+
|
132+
note: ...which requires type-checking `mutual_recursion`...
133+
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
140134
|
141135
LL | fn mutual_recursion() -> impl Sync {
142-
| --------- returning this opaque type `impl Sync`
143-
...
144-
LL | fn mutual_recursion_b() -> impl Sized {
145-
| ^^^^^^^^^^ recursive opaque type
146-
LL |
147-
LL | mutual_recursion()
148-
| ------------------ returning here with type `impl Sync`
136+
| ^^^^^^^^^
137+
= note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
138+
= note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
139+
note: cycle used when checking item types in top-level module
140+
--> $DIR/recursive-impl-trait-type-indirect.rs:8:1
141+
|
142+
LL | / #![feature(generators)]
143+
LL | | #![allow(unconditional_recursion)]
144+
LL | |
145+
LL | | fn option(i: i32) -> impl Sized {
146+
... |
147+
LL | |
148+
LL | | fn main() {}
149+
| |____________^
149150

150-
error: aborting due to 14 previous errors
151+
error: aborting due to 13 previous errors
151152

152-
For more information about this error, try `rustc --explain E0720`.
153+
Some errors have detailed explanations: E0391, E0720.
154+
For more information about an error, try `rustc --explain E0391`.

tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr

+22-20
Original file line numberDiff line numberDiff line change
@@ -118,30 +118,32 @@ LL | fn generator_hold() -> impl Sized {
118118
LL | let x = generator_hold();
119119
| - generator captures itself here
120120

121-
error[E0720]: cannot resolve opaque type
121+
error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
122122
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
123123
|
124124
LL | fn mutual_recursion() -> impl Sync {
125-
| ^^^^^^^^^ recursive opaque type
126-
LL |
127-
LL | mutual_recursion_b()
128-
| -------------------- returning here with type `impl Sized`
129-
...
130-
LL | fn mutual_recursion_b() -> impl Sized {
131-
| ---------- returning this opaque type `impl Sized`
132-
133-
error[E0720]: cannot resolve opaque type
134-
--> $DIR/recursive-impl-trait-type-indirect.rs:95:28
125+
| ^^^^^^^^^
126+
|
127+
note: ...which requires type-checking `mutual_recursion`...
128+
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
135129
|
136130
LL | fn mutual_recursion() -> impl Sync {
137-
| --------- returning this opaque type `impl Sync`
138-
...
139-
LL | fn mutual_recursion_b() -> impl Sized {
140-
| ^^^^^^^^^^ recursive opaque type
141-
LL |
142-
LL | mutual_recursion()
143-
| ------------------ returning here with type `impl Sync`
131+
| ^^^^^^^^^
132+
= note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
133+
= note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
134+
note: cycle used when checking item types in top-level module
135+
--> $DIR/recursive-impl-trait-type-indirect.rs:8:1
136+
|
137+
LL | / #![feature(generators)]
138+
LL | | #![allow(unconditional_recursion)]
139+
LL | |
140+
LL | | fn option(i: i32) -> impl Sized {
141+
... |
142+
LL | |
143+
LL | | fn main() {}
144+
| |____________^
144145

145-
error: aborting due to 14 previous errors
146+
error: aborting due to 13 previous errors
146147

147-
For more information about this error, try `rustc --explain E0720`.
148+
Some errors have detailed explanations: E0391, E0720.
149+
For more information about an error, try `rustc --explain E0391`.

tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr

+22-20
Original file line numberDiff line numberDiff line change
@@ -123,30 +123,32 @@ LL | | x;
123123
LL | | }
124124
| |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
125125

126-
error[E0720]: cannot resolve opaque type
126+
error[E0391]: cycle detected when computing type of `mutual_recursion::{opaque#0}`
127127
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
128128
|
129129
LL | fn mutual_recursion() -> impl Sync {
130-
| ^^^^^^^^^ recursive opaque type
131-
LL |
132-
LL | mutual_recursion_b()
133-
| -------------------- returning here with type `impl Sized`
134-
...
135-
LL | fn mutual_recursion_b() -> impl Sized {
136-
| ---------- returning this opaque type `impl Sized`
137-
138-
error[E0720]: cannot resolve opaque type
139-
--> $DIR/recursive-impl-trait-type-indirect.rs:95:28
130+
| ^^^^^^^^^
131+
|
132+
note: ...which requires type-checking `mutual_recursion`...
133+
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26
140134
|
141135
LL | fn mutual_recursion() -> impl Sync {
142-
| --------- returning this opaque type `impl Sync`
143-
...
144-
LL | fn mutual_recursion_b() -> impl Sized {
145-
| ^^^^^^^^^^ recursive opaque type
146-
LL |
147-
LL | mutual_recursion()
148-
| ------------------ returning here with type `impl Sync`
136+
| ^^^^^^^^^
137+
= note: ...which requires evaluating trait selection obligation `mutual_recursion_b::{opaque#0}: core::marker::Sync`...
138+
= note: ...which again requires computing type of `mutual_recursion::{opaque#0}`, completing the cycle
139+
note: cycle used when checking item types in top-level module
140+
--> $DIR/recursive-impl-trait-type-indirect.rs:8:1
141+
|
142+
LL | / #![feature(generators)]
143+
LL | | #![allow(unconditional_recursion)]
144+
LL | |
145+
LL | | fn option(i: i32) -> impl Sized {
146+
... |
147+
LL | |
148+
LL | | fn main() {}
149+
| |____________^
149150

150-
error: aborting due to 14 previous errors
151+
error: aborting due to 13 previous errors
151152

152-
For more information about this error, try `rustc --explain E0720`.
153+
Some errors have detailed explanations: E0391, E0720.
154+
For more information about an error, try `rustc --explain E0391`.

tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ fn mutual_recursion() -> impl Sync {
9393
}
9494

9595
fn mutual_recursion_b() -> impl Sized {
96-
//~^ ERROR
9796
mutual_recursion()
9897
}
9998

0 commit comments

Comments
 (0)