Skip to content

Commit 4aa2886

Browse files
committed
Auto merge of rust-lang#122077 - oli-obk:eager_opaque_checks4, r=<try>
Pass list of defineable opaque types into canonical queries This eliminates `DefiningAnchor::Bubble` for good and brings the old solver closer to the new one wrt cycles and nested obligations. At that point the difference between `DefiningAnchor::Bind([])` and `DefiningAnchor::Error` was academic. We only used the difference for some sanity checks, which actually had to be worked around in places, so I just removed `DefiningAnchor` entirely and just stored the list of opaques that may be defined. fixes rust-lang#108498 * [ ] run crater
2 parents 184c5ab + 5c618cd commit 4aa2886

36 files changed

+180
-236
lines changed

compiler/rustc_borrowck/src/consumers.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId;
44
use rustc_index::{IndexSlice, IndexVec};
55
use rustc_infer::infer::TyCtxtInferExt;
66
use rustc_middle::mir::{Body, Promoted};
7-
use rustc_middle::traits::DefiningAnchor;
87
use rustc_middle::ty::TyCtxt;
98
use std::rc::Rc;
109

@@ -106,7 +105,7 @@ pub fn get_body_with_borrowck_facts(
106105
options: ConsumerOptions,
107106
) -> BodyWithBorrowckFacts<'_> {
108107
let (input_body, promoted) = tcx.mir_promoted(def);
109-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
108+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
110109
let input_body: &Body<'_> = &input_body.borrow();
111110
let promoted: &IndexSlice<_, _> = &promoted.borrow();
112111
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()

compiler/rustc_borrowck/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use rustc_infer::infer::{
3232
use rustc_middle::mir::tcx::PlaceTy;
3333
use rustc_middle::mir::*;
3434
use rustc_middle::query::Providers;
35-
use rustc_middle::traits::DefiningAnchor;
3635
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
3736
use rustc_session::lint::builtin::UNUSED_MUT;
3837
use rustc_span::{Span, Symbol};
@@ -126,7 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
126125
return tcx.arena.alloc(result);
127126
}
128127

129-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
128+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
130129
let promoted: &IndexSlice<_, _> = &promoted.borrow();
131130
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
132131
debug!("mir_borrowck done");

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_infer::infer::InferCtxt;
77
use rustc_infer::infer::TyCtxtInferExt as _;
88
use rustc_infer::traits::{Obligation, ObligationCause};
99
use rustc_macros::extension;
10-
use rustc_middle::traits::DefiningAnchor;
1110
use rustc_middle::ty::visit::TypeVisitableExt;
1211
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
1312
use rustc_middle::ty::{GenericArgKind, GenericArgs};
@@ -146,6 +145,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
146145
opaque_type_key,
147146
universal_concrete_type,
148147
);
148+
149+
// Sometimes, when the hidden type is an inference variable, it can happen that
150+
// the hidden type becomes the opaque type itself. In this case, this was an opaque
151+
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
152+
// writeback.
153+
if let ty::Alias(ty::Opaque, alias_ty) = universal_concrete_type.ty.kind()
154+
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
155+
&& alias_ty.args == opaque_type_key.args
156+
{
157+
continue;
158+
}
149159
// Sometimes two opaque types are the same only after we remap the generic parameters
150160
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
151161
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
@@ -311,13 +321,13 @@ fn check_opaque_type_well_formed<'tcx>(
311321
parent_def_id = tcx.local_parent(parent_def_id);
312322
}
313323

314-
// FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])`
324+
// FIXME(-Znext-solver): We probably should use `&[]` instead of
315325
// and prepopulate this `InferCtxt` with known opaque values, rather than
316-
// using the `Bind` anchor here. For now it's fine.
326+
// allowing opaque types to be defined and checking them after the fact.
317327
let infcx = tcx
318328
.infer_ctxt()
319329
.with_next_trait_solver(next_trait_solver)
320-
.with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id))
330+
.with_opaque_type_inference(parent_def_id)
321331
.build();
322332
let ocx = ObligationCtxt::new(&infcx);
323333
let identity_args = GenericArgs::identity_for_item(tcx, def_id);

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1313
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
1414
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
1515
use rustc_middle::middle::stability::EvalResult;
16-
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
16+
use rustc_middle::traits::ObligationCauseCode;
1717
use rustc_middle::ty::fold::BottomUpFolder;
1818
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
1919
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -345,10 +345,7 @@ fn check_opaque_meets_bounds<'tcx>(
345345
};
346346
let param_env = tcx.param_env(defining_use_anchor);
347347

348-
let infcx = tcx
349-
.infer_ctxt()
350-
.with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor))
351-
.build();
348+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
352349
let ocx = ObligationCtxt::new(&infcx);
353350

354351
let args = match *origin {
@@ -1558,7 +1555,7 @@ pub(super) fn check_coroutine_obligations(
15581555
.ignoring_regions()
15591556
// Bind opaque types to type checking root, as they should have been checked by borrowck,
15601557
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1561-
.with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
1558+
.with_opaque_type_inference(typeck.hir_owner.def_id)
15621559
.build();
15631560

15641561
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);

compiler/rustc_hir_typeck/src/inherited.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_hir as hir;
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_hir::HirIdMap;
77
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
8-
use rustc_middle::traits::DefiningAnchor;
98
use rustc_middle::ty::visit::TypeVisitableExt;
109
use rustc_middle::ty::{self, Ty, TyCtxt};
1110
use rustc_span::def_id::LocalDefIdMap;
@@ -76,11 +75,7 @@ impl<'tcx> Inherited<'tcx> {
7675
pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
7776
let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
7877

79-
let infcx = tcx
80-
.infer_ctxt()
81-
.ignoring_regions()
82-
.with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id))
83-
.build();
78+
let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build();
8479
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
8580

8681
Inherited {

compiler/rustc_infer/src/infer/at.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<'tcx> InferCtxt<'tcx> {
7575
pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
7676
Self {
7777
tcx: self.tcx,
78-
defining_use_anchor: self.defining_use_anchor,
78+
defining_opaque_types: self.defining_opaque_types,
7979
considering_regions: self.considering_regions,
8080
skip_leak_check: self.skip_leak_check,
8181
inner: self.inner.clone(),

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl<'tcx> InferCtxt<'tcx> {
4545
let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
4646
self.tcx,
4747
param_env,
48+
self.defining_opaque_types,
4849
query_state,
4950
|tcx, param_env, query_state| {
5051
// FIXME(#118965): We don't canonicalize the static lifetimes that appear in the
@@ -540,6 +541,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
540541
max_universe: ty::UniverseIndex::ROOT,
541542
variables: List::empty(),
542543
value: (),
544+
defining_opaque_types: infcx.map(|i| i.defining_opaque_types).unwrap_or_default(),
543545
};
544546
Canonicalizer::canonicalize_with_base(
545547
base,
@@ -609,7 +611,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
609611
.max()
610612
.unwrap_or(ty::UniverseIndex::ROOT);
611613

612-
Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
614+
Canonical {
615+
max_universe,
616+
variables: canonical_variables,
617+
value: (base.value, out_value),
618+
defining_opaque_types: base.defining_opaque_types,
619+
}
613620
}
614621

615622
/// Creates a canonical variable replacing `kind` from the input,

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
3434
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
3535
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
3636
use rustc_middle::mir::ConstraintCategory;
37-
use rustc_middle::traits::{select, DefiningAnchor};
37+
use rustc_middle::traits::select;
3838
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3939
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
4040
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -234,18 +234,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
234234
pub struct InferCtxt<'tcx> {
235235
pub tcx: TyCtxt<'tcx>,
236236

237-
/// The `DefId` of the item in whose context we are performing inference or typeck.
238-
/// It is used to check whether an opaque type use is a defining use.
239-
///
240-
/// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
241-
/// the obligation. This frequently happens for
242-
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
243-
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
244-
///
245-
/// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined.
246-
/// This way it is easier to catch errors that
247-
/// might come up during inference or typeck.
248-
pub defining_use_anchor: DefiningAnchor<'tcx>,
237+
/// The `DefIds` of the opaque types that may have their hidden types constrained.
238+
pub defining_opaque_types: &'tcx ty::List<LocalDefId>,
249239

250240
/// Whether this inference context should care about region obligations in
251241
/// the root universe. Most notably, this is used during hir typeck as region
@@ -392,6 +382,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
392382
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
393383
self.probe_const_var(vid).ok()
394384
}
385+
386+
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
387+
self.defining_opaque_types
388+
}
395389
}
396390

397391
/// See the `error_reporting` module for more details.
@@ -606,7 +600,7 @@ impl fmt::Display for FixupError {
606600
/// Used to configure inference contexts before their creation.
607601
pub struct InferCtxtBuilder<'tcx> {
608602
tcx: TyCtxt<'tcx>,
609-
defining_use_anchor: DefiningAnchor<'tcx>,
603+
defining_opaque_types: &'tcx ty::List<LocalDefId>,
610604
considering_regions: bool,
611605
skip_leak_check: bool,
612606
/// Whether we are in coherence mode.
@@ -621,7 +615,7 @@ impl<'tcx> TyCtxt<'tcx> {
621615
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
622616
InferCtxtBuilder {
623617
tcx: self,
624-
defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()),
618+
defining_opaque_types: ty::List::empty(),
625619
considering_regions: true,
626620
skip_leak_check: false,
627621
intercrate: false,
@@ -637,8 +631,16 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
637631
/// It is only meant to be called in two places, for typeck
638632
/// (via `Inherited::build`) and for the inference context used
639633
/// in mir borrowck.
640-
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
641-
self.defining_use_anchor = defining_use_anchor;
634+
pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self {
635+
self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor);
636+
self
637+
}
638+
639+
pub fn with_defining_opaque_types(
640+
mut self,
641+
defining_opaque_types: &'tcx ty::List<LocalDefId>,
642+
) -> Self {
643+
self.defining_opaque_types = defining_opaque_types;
642644
self
643645
}
644646

@@ -670,30 +672,30 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
670672
/// the bound values in `C` to their instantiated values in `V`
671673
/// (in other words, `S(C) = V`).
672674
pub fn build_with_canonical<T>(
673-
&mut self,
675+
self,
674676
span: Span,
675677
canonical: &Canonical<'tcx, T>,
676678
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
677679
where
678680
T: TypeFoldable<TyCtxt<'tcx>>,
679681
{
680-
let infcx = self.build();
682+
let infcx = self.with_defining_opaque_types(canonical.defining_opaque_types).build();
681683
let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
682684
(infcx, value, args)
683685
}
684686

685687
pub fn build(&mut self) -> InferCtxt<'tcx> {
686688
let InferCtxtBuilder {
687689
tcx,
688-
defining_use_anchor,
690+
defining_opaque_types,
689691
considering_regions,
690692
skip_leak_check,
691693
intercrate,
692694
next_trait_solver,
693695
} = *self;
694696
InferCtxt {
695697
tcx,
696-
defining_use_anchor,
698+
defining_opaque_types,
697699
considering_regions,
698700
skip_leak_check,
699701
inner: RefCell::new(InferCtxtInner::new()),

compiler/rustc_infer/src/infer/opaque_types/mod.rs

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hir::OpaqueTyOrigin;
88
use rustc_data_structures::fx::FxIndexMap;
99
use rustc_data_structures::sync::Lrc;
1010
use rustc_hir as hir;
11-
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
11+
use rustc_middle::traits::ObligationCause;
1212
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1313
use rustc_middle::ty::fold::BottomUpFolder;
1414
use rustc_middle::ty::GenericArgKind;
@@ -109,48 +109,44 @@ impl<'tcx> InferCtxt<'tcx> {
109109
b,
110110
));
111111
}
112-
match self.defining_use_anchor {
113-
DefiningAnchor::Bind(_) => {
114-
// Check that this is `impl Trait` type is
115-
// declared by `parent_def_id` -- i.e., one whose
116-
// value we are inferring. At present, this is
117-
// always true during the first phase of
118-
// type-check, but not always true later on during
119-
// NLL. Once we support named opaque types more fully,
120-
// this same scenario will be able to arise during all phases.
121-
//
122-
// Here is an example using type alias `impl Trait`
123-
// that indicates the distinction we are checking for:
124-
//
125-
// ```rust
126-
// mod a {
127-
// pub type Foo = impl Iterator;
128-
// pub fn make_foo() -> Foo { .. }
129-
// }
130-
//
131-
// mod b {
132-
// fn foo() -> a::Foo { a::make_foo() }
133-
// }
134-
// ```
135-
//
136-
// Here, the return type of `foo` references an
137-
// `Opaque` indeed, but not one whose value is
138-
// presently being inferred. You can get into a
139-
// similar situation with closure return types
140-
// today:
141-
//
142-
// ```rust
143-
// fn foo() -> impl Iterator { .. }
144-
// fn bar() {
145-
// let x = || foo(); // returns the Opaque assoc with `foo`
146-
// }
147-
// ```
148-
if self.opaque_type_origin(def_id).is_none() {
149-
return None;
150-
}
151-
}
152-
DefiningAnchor::Bubble => {}
112+
// Check that this is `impl Trait` type is
113+
// declared by `parent_def_id` -- i.e., one whose
114+
// value we are inferring. At present, this is
115+
// always true during the first phase of
116+
// type-check, but not always true later on during
117+
// NLL. Once we support named opaque types more fully,
118+
// this same scenario will be able to arise during all phases.
119+
//
120+
// Here is an example using type alias `impl Trait`
121+
// that indicates the distinction we are checking for:
122+
//
123+
// ```rust
124+
// mod a {
125+
// pub type Foo = impl Iterator;
126+
// pub fn make_foo() -> Foo { .. }
127+
// }
128+
//
129+
// mod b {
130+
// fn foo() -> a::Foo { a::make_foo() }
131+
// }
132+
// ```
133+
//
134+
// Here, the return type of `foo` references an
135+
// `Opaque` indeed, but not one whose value is
136+
// presently being inferred. You can get into a
137+
// similar situation with closure return types
138+
// today:
139+
//
140+
// ```rust
141+
// fn foo() -> impl Iterator { .. }
142+
// fn bar() {
143+
// let x = || foo(); // returns the Opaque assoc with `foo`
144+
// }
145+
// ```
146+
if self.opaque_type_origin(def_id).is_none() {
147+
return None;
153148
}
149+
154150
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
155151
// We could accept this, but there are various ways to handle this situation, and we don't
156152
// want to make a decision on it right now. Likely this case is so super rare anyway, that
@@ -375,14 +371,9 @@ impl<'tcx> InferCtxt<'tcx> {
375371
/// in its defining scope.
376372
#[instrument(skip(self), level = "trace", ret)]
377373
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
378-
let defined_opaque_types = match self.defining_use_anchor {
379-
DefiningAnchor::Bubble => return None,
380-
DefiningAnchor::Bind(bind) => bind,
381-
};
382-
383374
let origin = self.tcx.opaque_type_origin(def_id);
384375

385-
defined_opaque_types.contains(&def_id).then_some(origin)
376+
self.defining_opaque_types.contains(&def_id).then_some(origin)
386377
}
387378
}
388379

0 commit comments

Comments
 (0)