Skip to content

Commit 052495d

Browse files
committed
Auto merge of rust-lang#98614 - oli-obk:take_unsound_opaque_types, r=wesleywiser
don't succeed `evaluate_obligation` query if new opaque types were registered fixes rust-lang#98608 fixes rust-lang#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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 14 additions & 4 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 0 additions & 8 deletions
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

Lines changed: 0 additions & 1 deletion
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))

0 commit comments

Comments
 (0)