Skip to content

Commit e41ca9a

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 based on rust-lang#121796 This eliminates `DefiningAnchor::Bubble` for good and brings the old solver closer to the new one wrt cycles and nested obligations. r? `@ghost`
2 parents 8039906 + 119a935 commit e41ca9a

File tree

76 files changed

+572
-415
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+572
-415
lines changed

compiler/rustc_borrowck/src/consumers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub fn get_body_with_borrowck_facts(
106106
options: ConsumerOptions,
107107
) -> BodyWithBorrowckFacts<'_> {
108108
let (input_body, promoted) = tcx.mir_promoted(def);
109-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
109+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
110110
let input_body: &Body<'_> = &input_body.borrow();
111111
let promoted: &IndexSlice<_, _> = &promoted.borrow();
112112
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()

compiler/rustc_borrowck/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
127127

128128
let hir_owner = tcx.local_def_id_to_hir_id(def).owner;
129129

130-
let infcx =
131-
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
130+
let infcx = tcx
131+
.infer_ctxt()
132+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, hir_owner.def_id))
133+
.build();
132134
let promoted: &IndexSlice<_, _> = &promoted.borrow();
133135
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
134136
debug!("mir_borrowck done");

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
146146
opaque_type_key,
147147
universal_concrete_type,
148148
);
149+
150+
// Sometimes, when the hidden type is an inference variable, it can happen that
151+
// the hidden type becomes the opaque type itself. In this case, this was an opaque
152+
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
153+
// writeback.
154+
if let ty::Alias(ty::Opaque, alias_ty) = universal_concrete_type.ty.kind()
155+
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
156+
&& alias_ty.args == opaque_type_key.args
157+
{
158+
continue;
159+
}
149160
// Sometimes two opaque types are the same only after we remap the generic parameters
150161
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
151162
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
@@ -317,7 +328,7 @@ fn check_opaque_type_well_formed<'tcx>(
317328
let infcx = tcx
318329
.infer_ctxt()
319330
.with_next_trait_solver(next_trait_solver)
320-
.with_opaque_type_inference(DefiningAnchor::Bind(parent_def_id))
331+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id))
321332
.build();
322333
let ocx = ObligationCtxt::new(&infcx);
323334
let identity_args = GenericArgs::identity_for_item(tcx, def_id);

compiler/rustc_hir/src/hir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -3605,6 +3605,10 @@ impl<'hir> Node<'hir> {
36053605
ImplItemKind::Type(ty) => Some(ty),
36063606
_ => None,
36073607
},
3608+
Node::ForeignItem(it) => match it.kind {
3609+
ForeignItemKind::Static(ty, _) => Some(ty),
3610+
_ => None,
3611+
},
36083612
_ => None,
36093613
}
36103614
}

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ fn check_opaque_meets_bounds<'tcx>(
346346

347347
let infcx = tcx
348348
.infer_ctxt()
349-
.with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
349+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor))
350350
.build();
351351
let ocx = ObligationCtxt::new(&infcx);
352352

@@ -1568,7 +1568,7 @@ pub(super) fn check_coroutine_obligations(
15681568
.ignoring_regions()
15691569
// Bind opaque types to type checking root, as they should have been checked by borrowck,
15701570
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1571-
.with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
1571+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
15721572
.build();
15731573

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

compiler/rustc_hir_typeck/src/inherited.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<'tcx> Inherited<'tcx> {
7979
let infcx = tcx
8080
.infer_ctxt()
8181
.ignoring_regions()
82-
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
82+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id))
8383
.build();
8484
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
8585

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

+8-1
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_use_anchor,
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_anchor: infcx.map(|i| i.defining_use_anchor).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_anchor: base.defining_anchor,
619+
}
613620
}
614621

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

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

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_index::Idx;
2222
use rustc_index::IndexVec;
2323
use rustc_middle::arena::ArenaAllocatable;
2424
use rustc_middle::mir::ConstraintCategory;
25+
use rustc_middle::traits::DefiningAnchor;
2526
use rustc_middle::ty::fold::TypeFoldable;
2627
use rustc_middle::ty::{self, BoundVar, Ty, TyCtxt};
2728
use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -163,6 +164,9 @@ impl<'tcx> InferCtxt<'tcx> {
163164
}
164165

165166
fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
167+
if self.defining_use_anchor == DefiningAnchor::Error {
168+
return vec![];
169+
}
166170
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.hidden_type.ty)).collect()
167171
}
168172

compiler/rustc_infer/src/infer/mod.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,11 @@ impl<'tcx> InferCtxtInner<'tcx> {
242242
pub struct InferCtxt<'tcx> {
243243
pub tcx: TyCtxt<'tcx>,
244244

245-
/// The `DefId` of the item in whose context we are performing inference or typeck.
246-
/// It is used to check whether an opaque type use is a defining use.
247-
///
248-
/// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
249-
/// the obligation. This frequently happens for
250-
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
251-
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
245+
/// The `DefIds` of the opaque types that may have their hidden types constrained.
252246
///
253247
/// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
254248
/// might come up during inference or typeck.
255-
pub defining_use_anchor: DefiningAnchor,
249+
pub defining_use_anchor: DefiningAnchor<'tcx>,
256250

257251
/// Whether this inference context should care about region obligations in
258252
/// the root universe. Most notably, this is used during hir typeck as region
@@ -399,6 +393,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
399393
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
400394
self.probe_const_var(vid).ok()
401395
}
396+
397+
fn defining_anchor(&self) -> DefiningAnchor<'tcx> {
398+
self.defining_use_anchor
399+
}
402400
}
403401

404402
/// See the `error_reporting` module for more details.
@@ -613,7 +611,7 @@ impl fmt::Display for FixupError {
613611
/// Used to configure inference contexts before their creation.
614612
pub struct InferCtxtBuilder<'tcx> {
615613
tcx: TyCtxt<'tcx>,
616-
defining_use_anchor: DefiningAnchor,
614+
defining_use_anchor: DefiningAnchor<'tcx>,
617615
considering_regions: bool,
618616
skip_leak_check: bool,
619617
/// Whether we are in coherence mode.
@@ -644,7 +642,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
644642
/// It is only meant to be called in two places, for typeck
645643
/// (via `Inherited::build`) and for the inference context used
646644
/// in mir borrowck.
647-
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
645+
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
648646
self.defining_use_anchor = defining_use_anchor;
649647
self
650648
}
@@ -677,14 +675,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
677675
/// the bound values in `C` to their instantiated values in `V`
678676
/// (in other words, `S(C) = V`).
679677
pub fn build_with_canonical<T>(
680-
&mut self,
678+
self,
681679
span: Span,
682680
canonical: &Canonical<'tcx, T>,
683681
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
684682
where
685683
T: TypeFoldable<TyCtxt<'tcx>>,
686684
{
687-
let infcx = self.build();
685+
let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build();
688686
let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
689687
(infcx, value, args)
690688
}

compiler/rustc_infer/src/infer/opaque_types.rs

+4-59
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ impl<'tcx> InferCtxt<'tcx> {
149149
return None;
150150
}
151151
}
152-
DefiningAnchor::Bubble => {}
153152
DefiningAnchor::Error => {
154153
return None;
155154
}
@@ -378,28 +377,14 @@ impl<'tcx> InferCtxt<'tcx> {
378377
/// in its defining scope.
379378
#[instrument(skip(self), level = "trace", ret)]
380379
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
381-
let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
382-
let parent_def_id = match self.defining_use_anchor {
383-
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
380+
let defined_opaque_types = match self.defining_use_anchor {
381+
DefiningAnchor::Error => return None,
384382
DefiningAnchor::Bind(bind) => bind,
385383
};
386384

387385
let origin = self.tcx.opaque_type_origin(def_id);
388-
let in_definition_scope = match origin {
389-
// Async `impl Trait`
390-
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
391-
// Anonymous `impl Trait`
392-
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
393-
// Named `type Foo = impl Bar;`
394-
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
395-
if in_assoc_ty {
396-
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
397-
} else {
398-
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
399-
}
400-
}
401-
};
402-
in_definition_scope.then_some(origin)
386+
387+
defined_opaque_types.contains(&def_id).then_some(origin)
403388
}
404389
}
405390

@@ -639,43 +624,3 @@ impl<'tcx> InferCtxt<'tcx> {
639624
}
640625
}
641626
}
642-
643-
/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
644-
///
645-
/// Example:
646-
/// ```ignore UNSOLVED (is this a bug?)
647-
/// # #![feature(type_alias_impl_trait)]
648-
/// pub mod foo {
649-
/// pub mod bar {
650-
/// pub trait Bar { /* ... */ }
651-
/// pub type Baz = impl Bar;
652-
///
653-
/// # impl Bar for () {}
654-
/// fn f1() -> Baz { /* ... */ }
655-
/// }
656-
/// fn f2() -> bar::Baz { /* ... */ }
657-
/// }
658-
/// ```
659-
///
660-
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
661-
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
662-
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
663-
fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
664-
let mut hir_id = tcx.local_def_id_to_hir_id(def_id);
665-
666-
// Named opaque types can be defined by any siblings or children of siblings.
667-
let scope = tcx.hir().get_defining_scope(opaque_hir_id);
668-
// We walk up the node tree until we hit the root or the scope of the opaque type.
669-
while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
670-
hir_id = tcx.hir().get_parent_item(hir_id).into();
671-
}
672-
// Syntactically, we are allowed to define the concrete type if:
673-
let res = hir_id == scope;
674-
trace!(
675-
"may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
676-
tcx.hir_node(hir_id),
677-
tcx.hir_node(opaque_hir_id),
678-
res
679-
);
680-
res
681-
}

compiler/rustc_middle/src/infer/canonical.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::ops::Index;
3333

3434
use crate::infer::MemberConstraint;
3535
use crate::mir::ConstraintCategory;
36+
use crate::traits::DefiningAnchor;
3637
use crate::ty::GenericArg;
3738
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
3839

@@ -153,11 +154,6 @@ pub struct QueryResponse<'tcx, R> {
153154
pub var_values: CanonicalVarValues<'tcx>,
154155
pub region_constraints: QueryRegionConstraints<'tcx>,
155156
pub certainty: Certainty,
156-
/// List of opaque types which we tried to compare to another type.
157-
/// Inside the query we don't know yet whether the opaque type actually
158-
/// should get its hidden type inferred. So we bubble the opaque type
159-
/// and the type it was compared against upwards and let the query caller
160-
/// handle it.
161157
pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
162158
pub value: R,
163159
}
@@ -316,6 +312,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
316312
&self,
317313
tcx: TyCtxt<'tcx>,
318314
key: ty::ParamEnv<'tcx>,
315+
defining_anchor: DefiningAnchor<'tcx>,
319316
state: &mut OriginalQueryValues<'tcx>,
320317
canonicalize_op: fn(
321318
TyCtxt<'tcx>,
@@ -330,6 +327,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
330327
max_universe: ty::UniverseIndex::ROOT,
331328
variables: List::empty(),
332329
value: key,
330+
defining_anchor,
333331
};
334332
}
335333

@@ -344,7 +342,8 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
344342
*canonical
345343
}
346344
Entry::Vacant(e) => {
347-
let canonical = canonicalize_op(tcx, key, state);
345+
let mut canonical = canonicalize_op(tcx, key, state);
346+
canonical.defining_anchor = defining_anchor;
348347
let OriginalQueryValues { var_values, universe_map } = state;
349348
assert_eq!(universe_map.len(), 1);
350349
e.insert((canonical, tcx.arena.alloc_slice(var_values)));

compiler/rustc_middle/src/mir/type_foldable.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! `TypeFoldable` implementations for MIR types
22
33
use rustc_ast::InlineAsmTemplatePiece;
4+
use rustc_hir::def_id::LocalDefId;
45

56
use super::*;
67

@@ -44,6 +45,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
4445
}
4546
}
4647

48+
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> {
49+
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
50+
self,
51+
_folder: &mut F,
52+
) -> Result<Self, F::Error> {
53+
Ok(self)
54+
}
55+
}
56+
4757
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
4858
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
4959
self,

compiler/rustc_middle/src/query/plumbing.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,10 @@ macro_rules! define_callbacks {
340340
<$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>
341341
>::Cache;
342342

343-
// Ensure that keys grow no larger than 64 bytes
343+
// Ensure that keys grow no larger than 72 bytes
344344
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
345345
const _: () = {
346-
if mem::size_of::<Key<'static>>() > 64 {
346+
if mem::size_of::<Key<'static>>() > 72 {
347347
panic!("{}", concat!(
348348
"the query `",
349349
stringify!($name),
@@ -354,10 +354,10 @@ macro_rules! define_callbacks {
354354
}
355355
};
356356

357-
// Ensure that values grow no larger than 64 bytes
357+
// Ensure that values grow no larger than 72 bytes
358358
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
359359
const _: () = {
360-
if mem::size_of::<Value<'static>>() > 64 {
360+
if mem::size_of::<Value<'static>>() > 72 {
361361
panic!("{}", concat!(
362362
"the query `",
363363
stringify!($name),

0 commit comments

Comments
 (0)