Skip to content

Commit 7ccdc2c

Browse files
committed
Pass list of defineable opaque types into canonical queries
1 parent 8031914 commit 7ccdc2c

28 files changed

+88
-129
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+11
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

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

+7-9
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,7 @@ 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.
237+
/// The `DefIds` of the opaque types that may have their hidden types constrained.
244238
///
245239
/// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined.
246240
/// This way it is easier to catch errors that
@@ -392,6 +386,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
392386
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
393387
self.probe_const_var(vid).ok()
394388
}
389+
390+
fn defining_anchor(&self) -> DefiningAnchor<'tcx> {
391+
self.defining_use_anchor
392+
}
395393
}
396394

397395
/// See the `error_reporting` module for more details.
@@ -670,14 +668,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
670668
/// the bound values in `C` to their instantiated values in `V`
671669
/// (in other words, `S(C) = V`).
672670
pub fn build_with_canonical<T>(
673-
&mut self,
671+
self,
674672
span: Span,
675673
canonical: &Canonical<'tcx, T>,
676674
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
677675
where
678676
T: TypeFoldable<TyCtxt<'tcx>>,
679677
{
680-
let infcx = self.build();
678+
let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build();
681679
let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
682680
(infcx, value, args)
683681
}

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

-2
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
}
154153
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
155154
// We could accept this, but there are various ways to handle this situation, and we don't
@@ -376,7 +375,6 @@ impl<'tcx> InferCtxt<'tcx> {
376375
#[instrument(skip(self), level = "trace", ret)]
377376
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
378377
let defined_opaque_types = match self.defining_use_anchor {
379-
DefiningAnchor::Bubble => return None,
380378
DefiningAnchor::Bind(bind) => bind,
381379
};
382380

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/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),

compiler/rustc_middle/src/traits/mod.rs

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

10221021
impl<'tcx> DefiningAnchor<'tcx> {

compiler/rustc_middle/src/traits/solve.rs

+1-2
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

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ use std::ops::{Bound, Deref};
8181
#[allow(rustc::usage_of_ty_tykind)]
8282
impl<'tcx> Interner for TyCtxt<'tcx> {
8383
type DefId = DefId;
84+
type DefiningAnchor = traits::DefiningAnchor<'tcx>;
8485
type AdtDef = ty::AdtDef<'tcx>;
8586
type GenericArgs = ty::GenericArgsRef<'tcx>;
8687
type GenericArg = ty::GenericArg<'tcx>;

compiler/rustc_next_trait_solver/src/canonicalizer.rs

+2-1
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

+3-4
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;
@@ -133,9 +133,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
133133
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
134134
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
135135
{
136-
let (infcx, key, canonical_inference_vars) = self
137-
.with_opaque_type_inference(DefiningAnchor::Bubble)
138-
.build_with_canonical(DUMMY_SP, canonical_key);
136+
let (infcx, key, canonical_inference_vars) =
137+
self.build_with_canonical(DUMMY_SP, canonical_key);
139138
let ocx = ObligationCtxt::new(&infcx);
140139
let value = operation(&ocx, key)?;
141140
ocx.make_canonicalized_query_response(canonical_inference_vars, value)

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

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
6565
&mut orig_values,
6666
QueryInput {
6767
goal,
68-
anchor: self.infcx.defining_use_anchor,
6968
predefined_opaques_in_body: self
7069
.tcx()
7170
.mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),

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

-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
226226
.infer_ctxt()
227227
.intercrate(intercrate)
228228
.with_next_trait_solver(true)
229-
.with_opaque_type_inference(canonical_input.value.anchor)
230229
.build_with_canonical(DUMMY_SP, &canonical_input);
231230

232231
let mut ecx = EvalCtxt {

compiler/rustc_trait_selection/src/solve/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -320,5 +320,6 @@ fn response_no_constraints_raw<'tcx>(
320320
external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
321321
certainty,
322322
},
323+
defining_anchor: Default::default(),
323324
}
324325
}

compiler/rustc_type_ir/src/canonical.rs

+6-4
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,8 +55,8 @@ 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

@@ -100,6 +101,7 @@ where
100101
value: self.value.try_fold_with(folder)?,
101102
max_universe: self.max_universe.try_fold_with(folder)?,
102103
variables: self.variables.try_fold_with(folder)?,
104+
defining_anchor: self.defining_anchor,
103105
})
104106
}
105107
}

compiler/rustc_type_ir/src/debug.rs

+4
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

+2
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

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010

1111
pub trait Interner: Sized {
1212
type DefId: Copy + Debug + Hash + Ord;
13+
type DefiningAnchor: Copy + Debug + Hash + Default;
1314
type AdtDef: Copy + Debug + Hash + Ord;
1415

1516
type GenericArgs: Copy

tests/ui/impl-trait/equality-in-canonical-query.clone.stderr

-23
This file was deleted.

tests/ui/impl-trait/equality-in-canonical-query.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
// issue: #116877
22
//@ revisions: sized clone
3-
//@[sized] check-pass
4-
//@[clone] known-bug: #108498
5-
//@[clone] failure-status: 101
6-
//@[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId("
7-
//@[clone] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> ""
8-
//@[clone] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> ""
9-
//@[clone] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> ""
10-
//@[clone] normalize-stderr-test: "(?m)note: delayed at.*$" -> ""
11-
//@[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> ""
12-
//@[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> ""
3+
//@ check-pass
134

145
#[cfg(sized)] fn rpit() -> impl Sized {}
156
#[cfg(clone)] fn rpit() -> impl Clone {}

0 commit comments

Comments
 (0)