Skip to content

Commit 126ff34

Browse files
Add some comments, add can_define_opaque_ty check to try_normalize_ty_recur
1 parent 2ecba0f commit 126ff34

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

compiler/rustc_trait_selection/src/solve/alias_relate.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22
//! Doing this via a separate goal is called "deferred alias relation" and part
33
//! of our more general approach to "lazy normalization".
44
//!
5-
//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches:
6-
//! * normalizes-to: If `A` is a projection, we can prove the equivalent
7-
//! projection predicate with B as the right-hand side of the projection.
8-
//! This goal is computed in both directions, if both are aliases.
9-
//! * subst-relate: Equate `A` and `B` by their substs, if they're both
10-
//! aliases with the same def-id.
11-
//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
12-
//! may apply, then we can compute the "intersection" of both normalizes-to by
13-
//! performing them together. This is used specifically to resolve ambiguities.
5+
//! This is done by first normalizing both sides of the goal, ending up in
6+
//! either a concrete type, rigid projection, opaque, or an infer variable.
7+
//! These are related further, described best with inline comments below.
8+
149
use super::EvalCtxt;
1510
use rustc_infer::infer::DefineOpaqueTypes;
1611
use rustc_infer::traits::query::NoSolution;
@@ -45,11 +40,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
4540
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
4641
}
4742

43+
// 1. When we have an alias being related to an infer var, then assign
44+
// the type (or const) of the alias to the infer var.
45+
// 2. When we have an opaque being related to a rigid type (which, due to 1,
46+
// is not an infer var), then assign the hidden type of the opaque to be
47+
// the rigid type.
48+
// 3. Otherwise, a rigid projection does not equal a concrete type ever.
4849
(Some(alias), None) => {
4950
if rhs.is_infer() {
5051
self.relate(param_env, lhs, variance, rhs)?;
5152
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
5253
} else if alias.is_opaque(tcx) {
54+
// FIXME: This doesn't account for variance.
5355
self.define_opaque(param_env, alias, rhs)
5456
} else {
5557
Err(NoSolution)
@@ -60,6 +62,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
6062
self.relate(param_env, lhs, variance, rhs)?;
6163
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
6264
} else if alias.is_opaque(tcx) {
65+
// FIXME: This doesn't account for variance.
6366
self.define_opaque(param_env, alias, lhs)
6467
} else {
6568
Err(NoSolution)
@@ -72,6 +75,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
7275
}
7376
}
7477

78+
// FIXME: This needs a name that reflects that it's okay to bottom-out with an inference var.
7579
/// Normalize the `term` to equate it later. This does not define opaque types.
7680
#[instrument(level = "debug", skip(self, param_env), ret)]
7781
fn try_normalize_term(

compiler/rustc_trait_selection/src/solve/mod.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_middle::traits::solve::{
2222
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, IsNormalizesToHack, QueryResult,
2323
Response,
2424
};
25+
use rustc_middle::traits::Reveal;
2526
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
2627
use rustc_middle::ty::{
2728
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
@@ -312,19 +313,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
312313
return Some(ty);
313314
};
314315

315-
// We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
316-
if let (DefineOpaqueTypes::No, ty::AliasKind::Opaque) = (define_opaque_types, kind) {
317-
if let Some(def_id) = alias.def_id.as_local() {
318-
if self
319-
.unify_existing_opaque_tys(
320-
param_env,
321-
OpaqueTypeKey { def_id, args: alias.args },
322-
self.next_ty_infer(),
323-
)
324-
.is_empty()
325-
{
326-
return Some(ty);
327-
}
316+
// We do no always define opaque types eagerly to allow non-defining uses
317+
// in the defining scope. However, if we can unify this opaque to an existing
318+
// opaque, then we should attempt to eagerly reveal the opaque, and we fall
319+
// through.
320+
if let DefineOpaqueTypes::No = define_opaque_types
321+
&& let Reveal::UserFacing = param_env.reveal()
322+
&& let ty::Opaque = kind
323+
&& let Some(def_id) = alias.def_id.as_local()
324+
&& self.can_define_opaque_ty(def_id)
325+
{
326+
if self
327+
.unify_existing_opaque_tys(
328+
param_env,
329+
OpaqueTypeKey { def_id, args: alias.args },
330+
self.next_ty_infer(),
331+
)
332+
.is_empty()
333+
{
334+
return Some(ty);
328335
}
329336
}
330337

0 commit comments

Comments
 (0)