Skip to content

Commit 052495d

Browse files
committed
Auto merge of #98614 - oli-obk:take_unsound_opaque_types, r=wesleywiser
don't succeed `evaluate_obligation` query if new opaque types were registered fixes #98608 fixes #98604 The root cause of all this is that in type flag computation we entirely ignore nongeneric things like struct fields and the signature of function items. So if a flag had to be set for a struct if it is set for a field, that will only happen if the field is generic, as only the generic parameters are checked. I now believe we cannot use type flags to handle opaque types. They seem like the wrong tool for this. Instead, this PR replaces the previous logic by adding a new variant of `EvaluatedToOk`: `EvaluatedToOkModuloOpaqueTypes`, which says that there were some opaque types that got hidden types bound, but that binding may not have been legal (because we don't know if the opaque type was in its defining scope or not).
2 parents 45263fc + d6b93eb commit 052495d

File tree

21 files changed

+116
-187
lines changed

21 files changed

+116
-187
lines changed

compiler/rustc_infer/src/infer/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
888888
.region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
889889
}
890890

891+
pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool {
892+
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
893+
}
894+
891895
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
892896
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
893897
}

compiler/rustc_infer/src/infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9595
}
9696
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
9797
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
98-
ty::Opaque(def_id, substs) => {
98+
ty::Opaque(def_id, substs) if def_id.is_local() => {
9999
let origin = if self.defining_use_anchor.is_some() {
100100
// Check that this is `impl Trait` type is
101101
// declared by `parent_def_id` -- i.e., one whose

compiler/rustc_infer/src/infer/undo_log.rs

+4
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
185185
})
186186
}
187187

188+
pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool {
189+
self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..)))
190+
}
191+
188192
pub(crate) fn region_constraints(
189193
&self,
190194
) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {

compiler/rustc_infer/src/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
203203
Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
204204
info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
205205
let mut ty = ty.clone();
206-
if result == EvaluationResult::EvaluatedToOk {
206+
if result.must_apply_considering_regions() {
207207
ty.obligations = vec![];
208208
}
209209
map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) });

compiler/rustc_middle/src/traits/select.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ pub enum EvaluationResult {
176176
EvaluatedToOk,
177177
/// Evaluation successful, but there were unevaluated region obligations.
178178
EvaluatedToOkModuloRegions,
179+
/// Evaluation successful, but need to rerun because opaque types got
180+
/// hidden types assigned without it being known whether the opaque types
181+
/// are within their defining scope
182+
EvaluatedToOkModuloOpaqueTypes,
179183
/// Evaluation is known to be ambiguous -- it *might* hold for some
180184
/// assignment of inference variables, but it might not.
181185
///
@@ -252,9 +256,11 @@ impl EvaluationResult {
252256

253257
pub fn may_apply(self) -> bool {
254258
match self {
255-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
256-
true
257-
}
259+
EvaluatedToOkModuloOpaqueTypes
260+
| EvaluatedToOk
261+
| EvaluatedToOkModuloRegions
262+
| EvaluatedToAmbig
263+
| EvaluatedToUnknown => true,
258264

259265
EvaluatedToErr | EvaluatedToRecur => false,
260266
}
@@ -264,7 +270,11 @@ impl EvaluationResult {
264270
match self {
265271
EvaluatedToUnknown | EvaluatedToRecur => true,
266272

267-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
273+
EvaluatedToOkModuloOpaqueTypes
274+
| EvaluatedToOk
275+
| EvaluatedToOkModuloRegions
276+
| EvaluatedToAmbig
277+
| EvaluatedToErr => false,
268278
}
269279
}
270280
}

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
10891089
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)]
10901090
#[derive(TypeFoldable, TypeVisitable)]
10911091
pub struct OpaqueTypeKey<'tcx> {
1092+
// FIXME(oli-obk): make this a LocalDefId
10921093
pub def_id: DefId,
10931094
pub substs: SubstsRef<'tcx>,
10941095
}

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
777777
Ok(
778778
EvaluationResult::EvaluatedToOk
779779
| EvaluationResult::EvaluatedToOkModuloRegions
780+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
780781
| EvaluationResult::EvaluatedToAmbig,
781782
) => {}
782783
_ => return false,

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

+4
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
394394
Err(_) => return Ok(EvaluatedToErr),
395395
}
396396

397+
if self.infcx.opaque_types_added_in_snapshot(snapshot) {
398+
return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
399+
}
400+
397401
match self.infcx.region_constraints_added_in_snapshot(snapshot) {
398402
None => Ok(result),
399403
Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),

compiler/rustc_type_ir/src/lib.rs

-8
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,6 @@ bitflags! {
204204
| TypeFlags::HAS_CT_INFER.bits
205205
| TypeFlags::HAS_TY_PLACEHOLDER.bits
206206
| TypeFlags::HAS_CT_PLACEHOLDER.bits
207-
// The `evaluate_obligation` query does not return further
208-
// obligations. If it evaluates an obligation with an opaque
209-
// type, that opaque type may get compared to another type,
210-
// constraining it. We would lose this information.
211-
// FIXME: differentiate between crate-local opaque types
212-
// and opaque types from other crates, as only opaque types
213-
// from the local crate can possibly be a local name
214-
| TypeFlags::HAS_TY_OPAQUE.bits
215207
// We consider 'freshened' types and constants
216208
// to depend on a particular fn.
217209
// The freshening process throws away information,

src/test/ui/impl-trait/auto-trait-leak.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ fn main() {
1111
// return type, which can't depend on the obligation.
1212
fn cycle1() -> impl Clone {
1313
//~^ ERROR cycle detected
14-
//~| ERROR cycle detected
1514
send(cycle2().clone());
1615

1716
Rc::new(Cell::new(5))

src/test/ui/impl-trait/auto-trait-leak.stderr

+15-97
Original file line numberDiff line numberDiff line change
@@ -30,129 +30,47 @@ note: ...which requires building MIR for `cycle1`...
3030
LL | fn cycle1() -> impl Clone {
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^
3232
note: ...which requires type-checking `cycle1`...
33-
--> $DIR/auto-trait-leak.rs:12:1
34-
|
35-
LL | fn cycle1() -> impl Clone {
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
37-
note: ...which requires computing type of `cycle2::{opaque#0}`...
38-
--> $DIR/auto-trait-leak.rs:20:16
39-
|
40-
LL | fn cycle2() -> impl Clone {
41-
| ^^^^^^^^^^
42-
note: ...which requires borrow-checking `cycle2`...
43-
--> $DIR/auto-trait-leak.rs:20:1
44-
|
45-
LL | fn cycle2() -> impl Clone {
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
47-
note: ...which requires processing `cycle2`...
48-
--> $DIR/auto-trait-leak.rs:20:1
49-
|
50-
LL | fn cycle2() -> impl Clone {
51-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
52-
note: ...which requires processing MIR for `cycle2`...
53-
--> $DIR/auto-trait-leak.rs:20:1
54-
|
55-
LL | fn cycle2() -> impl Clone {
56-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
57-
note: ...which requires unsafety-checking `cycle2`...
58-
--> $DIR/auto-trait-leak.rs:20:1
59-
|
60-
LL | fn cycle2() -> impl Clone {
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
62-
note: ...which requires building MIR for `cycle2`...
63-
--> $DIR/auto-trait-leak.rs:20:1
64-
|
65-
LL | fn cycle2() -> impl Clone {
66-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
67-
note: ...which requires type-checking `cycle2`...
68-
--> $DIR/auto-trait-leak.rs:20:1
69-
|
70-
LL | fn cycle2() -> impl Clone {
71-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
72-
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
73-
note: cycle used when checking item types in top-level module
74-
--> $DIR/auto-trait-leak.rs:1:1
75-
|
76-
LL | / use std::cell::Cell;
77-
LL | | use std::rc::Rc;
78-
LL | |
79-
LL | | fn send<T: Send>(_: T) {}
80-
... |
81-
LL | | Rc::new(String::from("foo"))
82-
LL | | }
83-
| |_^
84-
85-
error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
86-
--> $DIR/auto-trait-leak.rs:12:16
33+
--> $DIR/auto-trait-leak.rs:14:5
8734
|
88-
LL | fn cycle1() -> impl Clone {
89-
| ^^^^^^^^^^
90-
|
91-
note: ...which requires borrow-checking `cycle1`...
92-
--> $DIR/auto-trait-leak.rs:12:1
93-
|
94-
LL | fn cycle1() -> impl Clone {
95-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
96-
note: ...which requires processing `cycle1`...
97-
--> $DIR/auto-trait-leak.rs:12:1
98-
|
99-
LL | fn cycle1() -> impl Clone {
100-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
101-
note: ...which requires processing MIR for `cycle1`...
102-
--> $DIR/auto-trait-leak.rs:12:1
103-
|
104-
LL | fn cycle1() -> impl Clone {
105-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
106-
note: ...which requires unsafety-checking `cycle1`...
107-
--> $DIR/auto-trait-leak.rs:12:1
108-
|
109-
LL | fn cycle1() -> impl Clone {
110-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
111-
note: ...which requires building MIR for `cycle1`...
112-
--> $DIR/auto-trait-leak.rs:12:1
113-
|
114-
LL | fn cycle1() -> impl Clone {
115-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
116-
note: ...which requires type-checking `cycle1`...
117-
--> $DIR/auto-trait-leak.rs:12:1
118-
|
119-
LL | fn cycle1() -> impl Clone {
120-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
35+
LL | send(cycle2().clone());
36+
| ^^^^
37+
= note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
12138
note: ...which requires computing type of `cycle2::{opaque#0}`...
122-
--> $DIR/auto-trait-leak.rs:20:16
39+
--> $DIR/auto-trait-leak.rs:19:16
12340
|
12441
LL | fn cycle2() -> impl Clone {
12542
| ^^^^^^^^^^
12643
note: ...which requires borrow-checking `cycle2`...
127-
--> $DIR/auto-trait-leak.rs:20:1
44+
--> $DIR/auto-trait-leak.rs:19:1
12845
|
12946
LL | fn cycle2() -> impl Clone {
13047
| ^^^^^^^^^^^^^^^^^^^^^^^^^
13148
note: ...which requires processing `cycle2`...
132-
--> $DIR/auto-trait-leak.rs:20:1
49+
--> $DIR/auto-trait-leak.rs:19:1
13350
|
13451
LL | fn cycle2() -> impl Clone {
13552
| ^^^^^^^^^^^^^^^^^^^^^^^^^
13653
note: ...which requires processing MIR for `cycle2`...
137-
--> $DIR/auto-trait-leak.rs:20:1
54+
--> $DIR/auto-trait-leak.rs:19:1
13855
|
13956
LL | fn cycle2() -> impl Clone {
14057
| ^^^^^^^^^^^^^^^^^^^^^^^^^
14158
note: ...which requires unsafety-checking `cycle2`...
142-
--> $DIR/auto-trait-leak.rs:20:1
59+
--> $DIR/auto-trait-leak.rs:19:1
14360
|
14461
LL | fn cycle2() -> impl Clone {
14562
| ^^^^^^^^^^^^^^^^^^^^^^^^^
14663
note: ...which requires building MIR for `cycle2`...
147-
--> $DIR/auto-trait-leak.rs:20:1
64+
--> $DIR/auto-trait-leak.rs:19:1
14865
|
14966
LL | fn cycle2() -> impl Clone {
15067
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15168
note: ...which requires type-checking `cycle2`...
152-
--> $DIR/auto-trait-leak.rs:20:1
69+
--> $DIR/auto-trait-leak.rs:20:5
15370
|
154-
LL | fn cycle2() -> impl Clone {
155-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
71+
LL | send(cycle1().clone());
72+
| ^^^^
73+
= note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
15674
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
15775
note: cycle used when checking item types in top-level module
15876
--> $DIR/auto-trait-leak.rs:1:1
@@ -166,6 +84,6 @@ LL | | Rc::new(String::from("foo"))
16684
LL | | }
16785
| |_^
16886

169-
error: aborting due to 2 previous errors
87+
error: aborting due to previous error
17088

17189
For more information about this error, try `rustc --explain E0391`.

src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
mod m {
77
type Foo = impl std::fmt::Debug;
88
//~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
9-
//~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
109

1110
pub fn foo() -> Foo {
1211
22_u32

src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr

+5-22
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,18 @@ LL | type Foo = impl std::fmt::Debug;
55
| ^^^^^^^^^^^^^^^^^^^^
66
|
77
note: ...which requires type-checking `m::bar`...
8-
--> $DIR/auto-trait-leakage3.rs:15:5
8+
--> $DIR/auto-trait-leakage3.rs:15:9
99
|
10-
LL | pub fn bar() {
11-
| ^^^^^^^^^^^^
10+
LL | is_send(foo());
11+
| ^^^^^^^
12+
= note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
1213
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
1314
note: cycle used when checking item types in module `m`
1415
--> $DIR/auto-trait-leakage3.rs:6:1
1516
|
1617
LL | mod m {
1718
| ^^^^^
1819

19-
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
20-
--> $DIR/auto-trait-leakage3.rs:7:16
21-
|
22-
LL | type Foo = impl std::fmt::Debug;
23-
| ^^^^^^^^^^^^^^^^^^^^
24-
|
25-
note: ...which requires type-checking `m::bar`...
26-
--> $DIR/auto-trait-leakage3.rs:15:5
27-
|
28-
LL | pub fn bar() {
29-
| ^^^^^^^^^^^^
30-
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
31-
note: cycle used when checking item types in module `m`
32-
--> $DIR/auto-trait-leakage3.rs:6:1
33-
|
34-
LL | mod m {
35-
| ^^^^^
36-
37-
error: aborting due to 2 previous errors
20+
error: aborting due to previous error
3821

3922
For more information about this error, try `rustc --explain E0391`.

src/test/ui/type-alias-impl-trait/inference-cycle.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
mod m {
55
type Foo = impl std::fmt::Debug;
66
//~^ ERROR cycle detected
7-
//~| ERROR cycle detected
87

98
// Cycle: error today, but it'd be nice if it eventually worked
109

src/test/ui/type-alias-impl-trait/inference-cycle.stderr

+5-22
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,18 @@ LL | type Foo = impl std::fmt::Debug;
55
| ^^^^^^^^^^^^^^^^^^^^
66
|
77
note: ...which requires type-checking `m::bar`...
8-
--> $DIR/inference-cycle.rs:15:5
8+
--> $DIR/inference-cycle.rs:15:9
99
|
10-
LL | pub fn bar() {
11-
| ^^^^^^^^^^^^
10+
LL | is_send(foo()); // Today: error
11+
| ^^^^^^^
12+
= note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
1213
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
1314
note: cycle used when checking item types in module `m`
1415
--> $DIR/inference-cycle.rs:4:1
1516
|
1617
LL | mod m {
1718
| ^^^^^
1819

19-
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
20-
--> $DIR/inference-cycle.rs:5:16
21-
|
22-
LL | type Foo = impl std::fmt::Debug;
23-
| ^^^^^^^^^^^^^^^^^^^^
24-
|
25-
note: ...which requires type-checking `m::bar`...
26-
--> $DIR/inference-cycle.rs:15:5
27-
|
28-
LL | pub fn bar() {
29-
| ^^^^^^^^^^^^
30-
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
31-
note: cycle used when checking item types in module `m`
32-
--> $DIR/inference-cycle.rs:4:1
33-
|
34-
LL | mod m {
35-
| ^^^^^
36-
37-
error: aborting due to 2 previous errors
20+
error: aborting due to previous error
3821

3922
For more information about this error, try `rustc --explain E0391`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// edition:2018
2+
3+
type AsyncFnPtr = Box<
4+
dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>,
5+
>;
6+
7+
async fn test() {}
8+
9+
#[allow(unused_must_use)]
10+
fn main() {
11+
Box::new(test) as AsyncFnPtr;
12+
//~^ ERROR type mismatch
13+
}

0 commit comments

Comments
 (0)