Skip to content

Commit 19bd91d

Browse files
committed
Pass list of defineable opaque types into canonical queries
1 parent ea44ce0 commit 19bd91d

30 files changed

+101
-139
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
133133

134134
let ty =
135135
infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
136+
137+
// Sometimes, when the hidden type is an inference variable, it can happen that
138+
// the hidden type becomes the opaque type itself. In this case, this was an opaque
139+
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
140+
// writeback.
141+
// FIXME(-Znext-solver): This should be unnecessary with the new solver.
142+
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
143+
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
144+
&& alias_ty.args == opaque_type_key.args
145+
{
146+
continue;
147+
}
136148
// Sometimes two opaque types are the same only after we remap the generic parameters
137149
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
138150
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that

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_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/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
243243
pub struct InferCtxt<'tcx> {
244244
pub tcx: TyCtxt<'tcx>,
245245

246-
/// The `DefId` of the item in whose context we are performing inference or typeck.
247-
/// It is used to check whether an opaque type use is a defining use.
248-
///
249-
/// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
250-
/// the obligation. This frequently happens for
251-
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
252-
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
246+
/// The `DefIds` of the opaque types that may have their hidden types constrained.
253247
///
254248
/// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined.
255249
/// This way it is easier to catch errors that
@@ -401,6 +395,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
401395
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
402396
self.probe_const_var(vid).ok()
403397
}
398+
399+
fn defining_anchor(&self) -> DefiningAnchor<'tcx> {
400+
self.defining_use_anchor
401+
}
404402
}
405403

406404
/// See the `error_reporting` module for more details.
@@ -679,14 +677,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
679677
/// the bound values in `C` to their instantiated values in `V`
680678
/// (in other words, `S(C) = V`).
681679
pub fn build_with_canonical<T>(
682-
&mut self,
680+
self,
683681
span: Span,
684682
canonical: &Canonical<'tcx, T>,
685683
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
686684
where
687685
T: TypeFoldable<TyCtxt<'tcx>>,
688686
{
689-
let infcx = self.build();
687+
let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build();
690688
let (value, args) = infcx.instantiate_canonical(span, canonical);
691689
(infcx, value, args)
692690
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ impl<'tcx> InferCtxt<'tcx> {
146146
return None;
147147
}
148148
}
149-
DefiningAnchor::Bubble => {}
150149
}
151150
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
152151
// We could accept this, but there are various ways to handle this situation, and we don't
@@ -373,7 +372,6 @@ impl<'tcx> InferCtxt<'tcx> {
373372
#[instrument(skip(self), level = "trace", ret)]
374373
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
375374
let defined_opaque_types = match self.defining_use_anchor {
376-
DefiningAnchor::Bubble => return None,
377375
DefiningAnchor::Bind(bind) => bind,
378376
};
379377

compiler/rustc_middle/src/infer/canonical.rs

Lines changed: 5 additions & 6 deletions
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/query/plumbing.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,10 @@ macro_rules! define_callbacks {
338338

339339
pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
340340

341-
// Ensure that keys grow no larger than 64 bytes
341+
// Ensure that keys grow no larger than 72 bytes
342342
#[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))]
343343
const _: () = {
344-
if mem::size_of::<Key<'static>>() > 64 {
344+
if mem::size_of::<Key<'static>>() > 72 {
345345
panic!("{}", concat!(
346346
"the query `",
347347
stringify!($name),
@@ -352,10 +352,10 @@ macro_rules! define_callbacks {
352352
}
353353
};
354354

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

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,7 @@ pub enum CodegenObligationError {
10041004
/// opaques are replaced with inference vars eagerly in the old solver (e.g.
10051005
/// in projection, and in the signature during function type-checking).
10061006
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
1007+
#[derive(TyEncodable, TyDecodable)]
10071008
pub enum DefiningAnchor<'tcx> {
10081009
/// Define opaques which are in-scope of the current item being analyzed.
10091010
/// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`.
@@ -1012,14 +1013,12 @@ pub enum DefiningAnchor<'tcx> {
10121013
/// errors when handling opaque types, and also should be used when we would
10131014
/// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
10141015
Bind(&'tcx ty::List<LocalDefId>),
1015-
/// In contexts where we don't currently know what opaques are allowed to be
1016-
/// defined, such as (old solver) canonical queries, we will simply allow
1017-
/// opaques to be defined, but "bubble" them up in the canonical response or
1018-
/// otherwise treat them to be handled later.
1019-
///
1020-
/// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
1021-
/// which may affect what predicates pass and fail in the old trait solver.
1022-
Bubble,
1016+
}
1017+
1018+
impl Default for DefiningAnchor<'_> {
1019+
fn default() -> Self {
1020+
Self::Bind(ty::List::empty())
1021+
}
10231022
}
10241023

10251024
impl<'tcx> DefiningAnchor<'tcx> {

compiler/rustc_middle/src/traits/solve.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_span::def_id::DefId;
44

55
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
66
use crate::traits::query::NoSolution;
7-
use crate::traits::{Canonical, DefiningAnchor};
7+
use crate::traits::Canonical;
88
use crate::ty::{
99
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
1010
TypeVisitor,
@@ -114,7 +114,6 @@ impl MaybeCause {
114114
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
115115
pub struct QueryInput<'tcx, T> {
116116
pub goal: Goal<'tcx, T>,
117-
pub anchor: DefiningAnchor<'tcx>,
118117
pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
119118
}
120119

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ use std::ops::{Bound, Deref};
8484
#[allow(rustc::usage_of_ty_tykind)]
8585
impl<'tcx> Interner for TyCtxt<'tcx> {
8686
type DefId = DefId;
87+
type DefiningAnchor = traits::DefiningAnchor<'tcx>;
8788
type AdtDef = ty::AdtDef<'tcx>;
8889
type GenericArgs = ty::GenericArgsRef<'tcx>;
8990
type GenericArg = ty::GenericArg<'tcx>;

compiler/rustc_next_trait_solver/src/canonicalizer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infc
6969

7070
let (max_universe, variables) = canonicalizer.finalize();
7171

72-
Canonical { max_universe, variables, value }
72+
let defining_anchor = infcx.defining_anchor();
73+
Canonical { defining_anchor, max_universe, variables, value }
7374
}
7475

7576
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) {

compiler/rustc_trait_selection/src/infer.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
2-
use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext};
2+
use crate::traits::{self, ObligationCtxt, SelectionContext};
33

44
use crate::traits::TraitEngineExt as _;
55
use rustc_hir::def_id::DefId;
@@ -132,9 +132,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
132132
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
133133
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
134134
{
135-
let (infcx, key, canonical_inference_vars) = self
136-
.with_opaque_type_inference(DefiningAnchor::Bubble)
137-
.build_with_canonical(DUMMY_SP, canonical_key);
135+
let (infcx, key, canonical_inference_vars) =
136+
self.build_with_canonical(DUMMY_SP, canonical_key);
138137
let ocx = ObligationCtxt::new(&infcx);
139138
let value = operation(&ocx, key)?;
140139
ocx.make_canonicalized_query_response(canonical_inference_vars, value)

compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
6868
&mut orig_values,
6969
QueryInput {
7070
goal,
71-
anchor: self.infcx.defining_use_anchor,
7271
predefined_opaques_in_body: self
7372
.tcx()
7473
.mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),

compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
230230
.infer_ctxt()
231231
.intercrate(intercrate)
232232
.with_next_trait_solver(true)
233-
.with_opaque_type_inference(canonical_input.value.anchor)
234233
.build_with_canonical(DUMMY_SP, &canonical_input);
235234

236235
let mut ecx = EvalCtxt {

compiler/rustc_trait_selection/src/solve/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,6 @@ fn response_no_constraints_raw<'tcx>(
316316
external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
317317
certainty,
318318
},
319+
defining_anchor: Default::default(),
319320
}
320321
}

compiler/rustc_type_ir/src/canonical.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex};
1616
pub struct Canonical<I: Interner, V> {
1717
pub value: V,
1818
pub max_universe: UniverseIndex,
19+
pub defining_anchor: I::DefiningAnchor,
1920
pub variables: I::CanonicalVars,
2021
}
2122

@@ -44,8 +45,8 @@ impl<I: Interner, V> Canonical<I, V> {
4445
/// let b: Canonical<I, (T, Ty<I>)> = a.unchecked_map(|v| (v, ty));
4546
/// ```
4647
pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<I, W> {
47-
let Canonical { max_universe, variables, value } = self;
48-
Canonical { max_universe, variables, value: map_op(value) }
48+
let Canonical { defining_anchor, max_universe, variables, value } = self;
49+
Canonical { defining_anchor, max_universe, variables, value: map_op(value) }
4950
}
5051

5152
/// Allows you to map the `value` of a canonical while keeping the same set of
@@ -54,39 +55,41 @@ impl<I: Interner, V> Canonical<I, V> {
5455
/// **WARNING:** This function is very easy to mis-use, hence the name! See
5556
/// the comment of [Canonical::unchecked_map] for more details.
5657
pub fn unchecked_rebind<W>(self, value: W) -> Canonical<I, W> {
57-
let Canonical { max_universe, variables, value: _ } = self;
58-
Canonical { max_universe, variables, value }
58+
let Canonical { defining_anchor, max_universe, variables, value: _ } = self;
59+
Canonical { defining_anchor, max_universe, variables, value }
5960
}
6061
}
6162

6263
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
6364

6465
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
6566
fn eq(&self, other: &Self) -> bool {
66-
let Self { value, max_universe, variables } = self;
67+
let Self { value, max_universe, variables, defining_anchor } = self;
6768
*value == other.value
6869
&& *max_universe == other.max_universe
6970
&& *variables == other.variables
71+
&& *defining_anchor == other.defining_anchor
7072
}
7173
}
7274

7375
impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
7476
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75-
let Self { value, max_universe, variables } = self;
77+
let Self { value, max_universe, variables, defining_anchor } = self;
7678
write!(
7779
f,
78-
"Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?} }}",
80+
"Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_anchor: {defining_anchor:?} }}",
7981
)
8082
}
8183
}
8284

8385
impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> {
8486
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85-
let Self { value, max_universe, variables } = self;
87+
let Self { value, max_universe, variables, defining_anchor } = self;
8688
f.debug_struct("Canonical")
8789
.field("value", &value)
8890
.field("max_universe", &max_universe)
8991
.field("variables", &variables)
92+
.field("defining_anchor", &defining_anchor)
9093
.finish()
9194
}
9295
}
@@ -102,6 +105,7 @@ where
102105
value: self.value.try_fold_with(folder)?,
103106
max_universe: self.max_universe.try_fold_with(folder)?,
104107
variables: self.variables.try_fold_with(folder)?,
108+
defining_anchor: self.defining_anchor,
105109
})
106110
}
107111
}
@@ -111,9 +115,10 @@ where
111115
I::CanonicalVars: TypeVisitable<I>,
112116
{
113117
fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
114-
let Self { value, max_universe, variables } = self;
118+
let Self { value, max_universe, variables, defining_anchor } = self;
115119
try_visit!(value.visit_with(folder));
116120
try_visit!(max_universe.visit_with(folder));
121+
try_visit!(defining_anchor.visit_with(folder));
117122
variables.visit_with(folder)
118123
}
119124
}

compiler/rustc_type_ir/src/debug.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
4343
fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
4444
None
4545
}
46+
47+
fn defining_anchor(&self) -> <Self::Interner as Interner>::DefiningAnchor {
48+
Default::default()
49+
}
4650
}
4751

4852
pub trait DebugWithInfcx<I: Interner>: fmt::Debug {

compiler/rustc_type_ir/src/infcx.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ pub trait InferCtxtLike {
3737

3838
/// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type.
3939
fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
40+
41+
fn defining_anchor(&self) -> <Self::Interner as Interner>::DefiningAnchor;
4042
}

compiler/rustc_type_ir/src/interner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111

1212
pub trait Interner: Sized + Copy {
1313
type DefId: Copy + Debug + Hash + Eq;
14+
type DefiningAnchor: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
1415
type AdtDef: Copy + Debug + Hash + Eq;
1516

1617
type GenericArgs: Copy

0 commit comments

Comments
 (0)