Skip to content

Commit 4d80b80

Browse files
compiler-errorslcnr
andcommitted
Pull out logic from rust-lang#111131, plus some new logic in EvalCtxt::normalize_opaque_type
Co-authored-by: lcnr <rust@lcnr.de>
1 parent 7664dfe commit 4d80b80

File tree

13 files changed

+122
-43
lines changed

13 files changed

+122
-43
lines changed

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

+34-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
22
use super::{DefineOpaqueTypes, InferResult};
33
use crate::errors::OpaqueHiddenTypeDiag;
44
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
5-
use crate::traits;
5+
use crate::traits::{self, PredicateObligation};
66
use hir::def_id::{DefId, LocalDefId};
77
use hir::OpaqueTyOrigin;
88
use rustc_data_structures::fx::FxIndexMap;
@@ -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,26 @@ 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+
pub fn add_item_bounds_for_hidden_type(
561+
&self,
562+
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
563+
cause: ObligationCause<'tcx>,
564+
param_env: ty::ParamEnv<'tcx>,
565+
hidden_ty: Ty<'tcx>,
566+
obligations: &mut Vec<PredicateObligation<'tcx>>,
567+
) {
568+
let tcx = self.tcx;
546569
let item_bounds = tcx.explicit_item_bounds(def_id);
547570

548571
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
@@ -555,14 +578,15 @@ impl<'tcx> InferCtxt<'tcx> {
555578
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
556579
ty::Alias(ty::Projection, projection_ty)
557580
if !projection_ty.has_escaping_bound_vars()
558-
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
581+
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
582+
&& !tcx.trait_solver_next() =>
559583
{
560584
self.infer_projection(
561585
param_env,
562586
projection_ty,
563587
cause.clone(),
564588
0,
565-
&mut obligations,
589+
obligations,
566590
)
567591
}
568592
// Replace all other mentions of the same opaque type with the hidden type,
@@ -588,10 +612,10 @@ impl<'tcx> InferCtxt<'tcx> {
588612
predicate.kind().skip_binder()
589613
{
590614
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![] });
615+
// No point on adding any obligations since there's a type error involved.
616+
obligations.clear();
617+
return;
593618
}
594-
trace!("{:#?}", projection.term);
595619
}
596620
// Require that the predicate holds for the concrete type.
597621
debug!(?predicate);
@@ -602,7 +626,6 @@ impl<'tcx> InferCtxt<'tcx> {
602626
predicate,
603627
));
604628
}
605-
Ok(InferOk { value: (), obligations })
606629
}
607630
}
608631

compiler/rustc_infer/src/infer/sub.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
131131
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
132132
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
133133
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
134-
&& def_id.is_local() =>
134+
&& def_id.is_local()
135+
&& !self.tcx().trait_solver_next() =>
135136
{
136137
self.fields.obligations.extend(
137138
infcx

compiler/rustc_middle/src/ty/mod.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -996,17 +996,11 @@ impl<'tcx> Term<'tcx> {
996996
}
997997
}
998998

999-
/// This function returns the inner `AliasTy` if this term is a projection.
1000-
///
1001-
/// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
1002-
/// deal with constants.
1003-
pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
999+
/// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`.
1000+
pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
10041001
match self.unpack() {
1005-
TermKind::Ty(ty) => match ty.kind() {
1006-
ty::Alias(kind, alias_ty) => match kind {
1007-
AliasKind::Projection | AliasKind::Inherent => Some(*alias_ty),
1008-
AliasKind::Opaque => None,
1009-
},
1002+
TermKind::Ty(ty) => match *ty.kind() {
1003+
ty::Alias(_kind, alias_ty) => Some(alias_ty),
10101004
_ => None,
10111005
},
10121006
TermKind::Const(ct) => match ct.kind() {

compiler/rustc_trait_selection/src/solve/fulfill.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
133133
| ty::PredicateKind::ObjectSafe(_)
134134
| ty::PredicateKind::ClosureKind(_, _, _)
135135
| ty::PredicateKind::ConstEvaluatable(_)
136-
| ty::PredicateKind::TypeWellFormedFromEnv(_)
137136
| ty::PredicateKind::Ambiguous => {
138137
FulfillmentErrorCode::CodeSelectionError(
139138
SelectionError::Unimplemented,
140139
)
141140
}
141+
ty::PredicateKind::TypeWellFormedFromEnv(_) => {
142+
bug!("unexpected goal: {goal:?}")
143+
}
142144
},
143145
root_obligation: obligation,
144146
});

compiler/rustc_trait_selection/src/solve/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mod assembly;
2424
mod canonicalize;
2525
mod eval_ctxt;
2626
mod fulfill;
27+
mod opaques;
2728
mod project_goals;
2829
mod search_graph;
2930
mod trait_goals;
@@ -212,7 +213,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
212213
);
213214
}
214215

215-
match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
216+
match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
216217
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
217218

218219
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use rustc_infer::infer::InferOk;
2+
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
3+
use rustc_middle::traits::{ObligationCause, Reveal};
4+
use rustc_middle::ty::ProjectionPredicate;
5+
6+
use super::{EvalCtxt, SolverMode};
7+
8+
impl<'tcx> EvalCtxt<'_, 'tcx> {
9+
pub(super) fn normalize_opaque_type(
10+
&mut self,
11+
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
12+
) -> QueryResult<'tcx> {
13+
let tcx = self.tcx();
14+
let opaque_ty = goal.predicate.projection_ty;
15+
let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
16+
17+
match goal.param_env.reveal() {
18+
Reveal::UserFacing => match self.solver_mode() {
19+
SolverMode::Normal => self.probe(|ecx| {
20+
// FIXME: Check that the usage is "defining" (all free params), otherwise bail.
21+
// FIXME: This should probably just check the anchor directly
22+
let InferOk { value: (), obligations } = self.infcx.handle_opaque_type(
23+
expected,
24+
tcx.mk_opaque(opaque_ty.def_id, opaque_ty.substs),
25+
true,
26+
&ObligationCause::dummy(),
27+
goal.param_env,
28+
)?;
29+
// FIXME: Need to fold these to replace the opaque ty with the expected ty.
30+
ecx.add_goals(obligations.into_iter().map(Into::into));
31+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
32+
}),
33+
SolverMode::Coherence => {
34+
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
35+
}
36+
},
37+
Reveal::All => self.probe(|ecx| {
38+
let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs);
39+
ecx.eq(goal.param_env, expected, actual)?;
40+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
41+
}),
42+
}
43+
}
44+
}

compiler/rustc_trait_selection/src/solve/project_goals.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
3030
// `U` and equate it with `u32`. This means that we don't need a separate
3131
// projection cache in the solver.
3232
if self.term_is_fully_unconstrained(goal) {
33-
let candidates = self.assemble_and_evaluate_candidates(goal);
34-
self.merge_candidates(candidates)
33+
match goal.predicate.projection_ty.kind(self.tcx()) {
34+
ty::AliasKind::Projection => {
35+
let candidates = self.assemble_and_evaluate_candidates(goal);
36+
self.merge_candidates(candidates)
37+
}
38+
ty::AliasKind::Opaque => self.normalize_opaque_type(goal),
39+
}
3540
} else {
3641
self.set_normalizes_to_hack_goal(goal);
3742
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
834834
| ty::PredicateKind::Subtype(..)
835835
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
836836
| ty::PredicateKind::ConstEvaluatable(..)
837-
| ty::PredicateKind::Coerce(..)
838-
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
837+
| ty::PredicateKind::Coerce(..) => {}
838+
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
839+
bug!("predicate should only exist in the environment: {bound_predicate:?}")
840+
}
839841
ty::PredicateKind::Ambiguous => return false,
840842
};
841843
}

compiler/rustc_traits/src/chalk/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
679679
| ty::PredicateKind::ConstEquate(..)
680680
| ty::PredicateKind::Ambiguous
681681
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
682-
bug!("unexpected predicate {}", &self)
682+
bug!("unexpected predicate {self}")
683683
}
684684
};
685685
value.map(|value| chalk_ir::Binders::new(binders, value))

0 commit comments

Comments
 (0)