Skip to content

Commit eb9da7b

Browse files
committed
Auto merge of #111473 - compiler-errors:opaques, r=lcnr
Handle opaques in the new solver (take 2?) Implement a new strategy for handling opaques in the new solver. First, queries now carry both their defining anchor and the opaques that were defined in the inference context at the time of canonicalization. These are both used to pre-populate the inference context used by the canonical query. Second, use the normalizes-to goal to handle opaque types in the new solver. This means that opaques are handled like projection aliases, but with their own rules: * Can only define opaques if they're "defining uses" (i.e. have unique params in all their substs). * Can only define opaques that are from the anchor. * Opaque type definitions are modulo regions. So that means `Opaque<'?0r> = HiddenTy1` and `Opaque<?'1r> = HiddenTy2` equate `HiddenTy1` and `HiddenTy2` instead of defining them as different opaque type keys.
2 parents 0b011b7 + dd98198 commit eb9da7b

Some content is hidden

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

42 files changed

+658
-189
lines changed

compiler/rustc_borrowck/src/consumers.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_index::{IndexSlice, IndexVec};
7-
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
7+
use rustc_infer::infer::TyCtxtInferExt;
88
use rustc_middle::mir::{Body, Promoted};
9+
use rustc_middle::traits::DefiningAnchor;
910
use rustc_middle::ty::TyCtxt;
1011
use std::rc::Rc;
1112

compiler/rustc_borrowck/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_hir::def_id::LocalDefId;
2626
use rustc_index::bit_set::ChunkedBitSet;
2727
use rustc_index::{IndexSlice, IndexVec};
2828
use rustc_infer::infer::{
29-
DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
29+
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
3030
};
3131
use rustc_middle::mir::{
3232
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
@@ -36,6 +36,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind
3636
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
3737
use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
3838
use rustc_middle::query::Providers;
39+
use rustc_middle::traits::DefiningAnchor;
3940
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
4041
use rustc_session::lint::builtin::UNUSED_MUT;
4142
use rustc_span::{Span, Symbol};

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
22
use rustc_errors::ErrorGuaranteed;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_hir::OpaqueTyOrigin;
5+
use rustc_infer::infer::InferCtxt;
56
use rustc_infer::infer::TyCtxtInferExt as _;
6-
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
77
use rustc_infer::traits::{Obligation, ObligationCause};
8+
use rustc_middle::traits::DefiningAnchor;
89
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
910
use rustc_middle::ty::visit::TypeVisitableExt;
1011
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};

compiler/rustc_borrowck/src/type_check/mod.rs

+61
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
4848
use rustc_mir_dataflow::move_paths::MoveData;
4949
use rustc_mir_dataflow::ResultsCursor;
5050

51+
use crate::renumber::RegionCtxt;
5152
use crate::session_diagnostics::MoveUnsized;
5253
use crate::{
5354
borrow_set::BorrowSet,
@@ -183,6 +184,15 @@ pub(crate) fn type_check<'mir, 'tcx>(
183184
&mut borrowck_context,
184185
);
185186

187+
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
188+
// predefined opaques in the typeck root.
189+
// FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
190+
// the HIR typeck map defining usages back to their definition params,
191+
// they won't actually match up with the usages in this body...
192+
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
193+
checker.register_predefined_opaques_in_new_solver();
194+
}
195+
186196
let mut verifier = TypeVerifier::new(&mut checker, promoted);
187197
verifier.visit_body(&body);
188198

@@ -1023,6 +1033,57 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10231033
checker
10241034
}
10251035

1036+
pub(super) fn register_predefined_opaques_in_new_solver(&mut self) {
1037+
// OK to use the identity substitutions for each opaque type key, since
1038+
// we remap opaques from HIR typeck back to their definition params.
1039+
let opaques: Vec<_> = self
1040+
.infcx
1041+
.tcx
1042+
.typeck(self.body.source.def_id().expect_local())
1043+
.concrete_opaque_types
1044+
.iter()
1045+
.map(|(&def_id, &hidden_ty)| {
1046+
let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
1047+
(ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
1048+
})
1049+
.collect();
1050+
1051+
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
1052+
self.infcx.next_nll_region_var(
1053+
NllRegionVariableOrigin::Existential { from_forall: false },
1054+
|| RegionCtxt::Unknown,
1055+
)
1056+
});
1057+
1058+
let param_env = self.param_env;
1059+
let result = self.fully_perform_op(
1060+
Locations::All(self.body.span),
1061+
ConstraintCategory::OpaqueType,
1062+
CustomTypeOp::new(
1063+
|ocx| {
1064+
for (key, hidden_ty) in renumbered_opaques {
1065+
ocx.register_infer_ok_obligations(
1066+
ocx.infcx.register_hidden_type_in_new_solver(
1067+
key,
1068+
param_env,
1069+
hidden_ty.ty,
1070+
)?,
1071+
);
1072+
}
1073+
Ok(())
1074+
},
1075+
"register pre-defined opaques",
1076+
),
1077+
);
1078+
1079+
if result.is_err() {
1080+
self.infcx.tcx.sess.delay_span_bug(
1081+
self.body.span,
1082+
"failed re-defining predefined opaques in mir typeck",
1083+
);
1084+
}
1085+
}
1086+
10261087
fn body(&self) -> &Body<'tcx> {
10271088
self.body
10281089
}

compiler/rustc_const_eval/src/util/compare_types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
//! FIXME: Move this to a more general place. The utility of this extends to
44
//! other areas of the compiler as well.
55
6-
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
7-
use rustc_infer::traits::ObligationCause;
6+
use rustc_infer::infer::TyCtxtInferExt;
7+
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
88
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
99
use rustc_trait_selection::traits::ObligationCtxt;
1010

compiler/rustc_hir_analysis/src/check/check.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ use rustc_hir::intravisit::Visitor;
1313
use rustc_hir::{ItemKind, Node, PathSegment};
1414
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
1515
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
16-
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
16+
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1717
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
1818
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
1919
use rustc_middle::hir::nested_filter;
2020
use rustc_middle::middle::stability::EvalResult;
21+
use rustc_middle::traits::DefiningAnchor;
2122
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
2223
use rustc_middle::ty::subst::GenericArgKind;
2324
use rustc_middle::ty::util::{Discr, IntTypeExt};

compiler/rustc_hir_typeck/src/inherited.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_hir as hir;
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_hir::HirIdMap;
7-
use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
7+
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
8+
use rustc_middle::traits::DefiningAnchor;
89
use rustc_middle::ty::visit::TypeVisitableExt;
910
use rustc_middle::ty::{self, Ty, TyCtxt};
1011
use rustc_span::def_id::LocalDefIdMap;

compiler/rustc_infer/src/infer/combine.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,7 @@ impl<'tcx> InferCtxt<'tcx> {
113113
bug!()
114114
}
115115

116-
(_, ty::Alias(AliasKind::Projection | AliasKind::Inherent, _))
117-
| (ty::Alias(AliasKind::Projection | AliasKind::Inherent, _), _)
118-
if self.tcx.trait_solver_next() =>
119-
{
116+
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
120117
relation.register_type_relate_obligation(a, b);
121118
Ok(a)
122119
}

compiler/rustc_infer/src/infer/equate.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
104104
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
105105
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
106106
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
107-
&& def_id.is_local() =>
107+
&& def_id.is_local()
108+
&& !self.tcx().trait_solver_next() =>
108109
{
109110
self.fields.obligations.extend(
110111
infcx

compiler/rustc_infer/src/infer/lattice.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,12 @@ where
108108
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
109109
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
110110
) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
111+
111112
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
112113
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
113-
if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() =>
114+
if this.define_opaque_types() == DefineOpaqueTypes::Yes
115+
&& def_id.is_local()
116+
&& !this.tcx().trait_solver_next() =>
114117
{
115118
this.register_obligations(
116119
infcx

compiler/rustc_infer/src/infer/mod.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
2424
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
2525
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
2626
use rustc_middle::mir::ConstraintCategory;
27-
use rustc_middle::traits::select;
27+
use rustc_middle::traits::{select, DefiningAnchor};
2828
use rustc_middle::ty::error::{ExpectedFound, TypeError};
2929
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
3030
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -231,17 +231,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
231231
}
232232
}
233233

234-
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
235-
pub enum DefiningAnchor {
236-
/// `DefId` of the item.
237-
Bind(LocalDefId),
238-
/// When opaque types are not resolved, we `Bubble` up, meaning
239-
/// return the opaque/hidden type pair from query, for caller of query to handle it.
240-
Bubble,
241-
/// Used to catch type mismatch errors when handling opaque types.
242-
Error,
243-
}
244-
245234
pub struct InferCtxt<'tcx> {
246235
pub tcx: TyCtxt<'tcx>,
247236

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

+14-8
Original file line numberDiff line numberDiff line change
@@ -491,16 +491,22 @@ where
491491
(
492492
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
493493
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
494-
) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
495-
self.tcx().sess.delay_span_bug(
496-
self.delegate.span(),
497-
"failure to relate an opaque to itself should result in an error later on",
498-
);
499-
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
500-
}),
494+
) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
495+
infcx.super_combine_tys(self, a, b).or_else(|err| {
496+
// This behavior is only there for the old solver, the new solver
497+
// shouldn't ever fail. Instead, it unconditionally emits an
498+
// alias-relate goal.
499+
assert!(!self.tcx().trait_solver_next());
500+
self.tcx().sess.delay_span_bug(
501+
self.delegate.span(),
502+
"failure to relate an opaque to itself should result in an error later on",
503+
);
504+
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
505+
})
506+
}
501507
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
502508
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
503-
if def_id.is_local() =>
509+
if def_id.is_local() && !self.tcx().trait_solver_next() =>
504510
{
505511
self.relate_opaques(a, b)
506512
}

compiler/rustc_infer/src/infer/opaque_types.rs

+59-13
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
22
use super::{DefineOpaqueTypes, InferResult};
33
use crate::errors::OpaqueHiddenTypeDiag;
4-
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
5-
use crate::traits;
4+
use crate::infer::{InferCtxt, InferOk};
5+
use crate::traits::{self, PredicateObligation};
66
use hir::def_id::{DefId, LocalDefId};
77
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::ObligationCause;
11+
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
1212
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1313
use rustc_middle::ty::fold::BottomUpFolder;
1414
use rustc_middle::ty::GenericArgKind;
@@ -48,9 +48,15 @@ impl<'tcx> InferCtxt<'tcx> {
4848
span: Span,
4949
param_env: ty::ParamEnv<'tcx>,
5050
) -> InferOk<'tcx, T> {
51+
// We handle opaque types differently in the new solver.
52+
if self.tcx.trait_solver_next() {
53+
return InferOk { value, obligations: vec![] };
54+
}
55+
5156
if !value.has_opaque_types() {
5257
return InferOk { value, obligations: vec![] };
5358
}
59+
5460
let mut obligations = vec![];
5561
let replace_opaque_type = |def_id: DefId| {
5662
def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
@@ -521,17 +527,14 @@ impl<'tcx> InferCtxt<'tcx> {
521527
origin: hir::OpaqueTyOrigin,
522528
a_is_expected: bool,
523529
) -> InferResult<'tcx, ()> {
524-
let tcx = self.tcx;
525-
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
526-
527530
// Ideally, we'd get the span where *this specific `ty` came
528531
// from*, but right now we just use the span from the overall
529532
// value being folded. In simple cases like `-> impl Foo`,
530533
// these are the same span, but not in cases like `-> (impl
531534
// Foo, impl Bar)`.
532535
let span = cause.span;
533536
let prev = self.inner.borrow_mut().opaque_types().register(
534-
OpaqueTypeKey { def_id, substs },
537+
opaque_type_key,
535538
OpaqueHiddenType { ty: hidden_ty, span },
536539
origin,
537540
);
@@ -543,6 +546,49 @@ impl<'tcx> InferCtxt<'tcx> {
543546
Vec::new()
544547
};
545548

549+
self.add_item_bounds_for_hidden_type(
550+
opaque_type_key,
551+
cause,
552+
param_env,
553+
hidden_ty,
554+
&mut obligations,
555+
);
556+
557+
Ok(InferOk { value: (), obligations })
558+
}
559+
560+
/// Registers an opaque's hidden type -- only should be used when the opaque
561+
/// can be defined. For something more fallible -- checks the anchors, tries
562+
/// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
563+
pub fn register_hidden_type_in_new_solver(
564+
&self,
565+
opaque_type_key: OpaqueTypeKey<'tcx>,
566+
param_env: ty::ParamEnv<'tcx>,
567+
hidden_ty: Ty<'tcx>,
568+
) -> InferResult<'tcx, ()> {
569+
assert!(self.tcx.trait_solver_next());
570+
let origin = self
571+
.opaque_type_origin(opaque_type_key.def_id)
572+
.expect("should be called for defining usages only");
573+
self.register_hidden_type(
574+
opaque_type_key,
575+
ObligationCause::dummy(),
576+
param_env,
577+
hidden_ty,
578+
origin,
579+
true,
580+
)
581+
}
582+
583+
pub fn add_item_bounds_for_hidden_type(
584+
&self,
585+
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
586+
cause: ObligationCause<'tcx>,
587+
param_env: ty::ParamEnv<'tcx>,
588+
hidden_ty: Ty<'tcx>,
589+
obligations: &mut Vec<PredicateObligation<'tcx>>,
590+
) {
591+
let tcx = self.tcx;
546592
let item_bounds = tcx.explicit_item_bounds(def_id);
547593

548594
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
@@ -555,14 +601,15 @@ impl<'tcx> InferCtxt<'tcx> {
555601
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
556602
ty::Alias(ty::Projection, projection_ty)
557603
if !projection_ty.has_escaping_bound_vars()
558-
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
604+
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
605+
&& !tcx.trait_solver_next() =>
559606
{
560607
self.infer_projection(
561608
param_env,
562609
projection_ty,
563610
cause.clone(),
564611
0,
565-
&mut obligations,
612+
obligations,
566613
)
567614
}
568615
// Replace all other mentions of the same opaque type with the hidden type,
@@ -588,10 +635,10 @@ impl<'tcx> InferCtxt<'tcx> {
588635
predicate.kind().skip_binder()
589636
{
590637
if projection.term.references_error() {
591-
// No point on adding these obligations since there's a type error involved.
592-
return Ok(InferOk { value: (), obligations: vec![] });
638+
// No point on adding any obligations since there's a type error involved.
639+
obligations.clear();
640+
return;
593641
}
594-
trace!("{:#?}", projection.term);
595642
}
596643
// Require that the predicate holds for the concrete type.
597644
debug!(?predicate);
@@ -602,7 +649,6 @@ impl<'tcx> InferCtxt<'tcx> {
602649
predicate,
603650
));
604651
}
605-
Ok(InferOk { value: (), obligations })
606652
}
607653
}
608654

0 commit comments

Comments
 (0)