Skip to content

Commit 60e068f

Browse files
committed
address review
1 parent 9aa065b commit 60e068f

4 files changed

Lines changed: 60 additions & 23 deletions

File tree

compiler/rustc_infer/src/infer/relate/generalize.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,46 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
355355
}
356356
}
357357

358+
/// This state determines how generalization treats aliases.
359+
///
360+
/// Based on which state we're in, we treat them either as rigid or normalizable,
361+
/// which might change depending on what types the generalization visitor encounters.
362+
/// See `handle_alias_ty` for the logic of how we change states.
358363
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
359364
enum GeneralizerState {
360365
/// Treat aliases as potentially normalizable.
366+
///
367+
/// This is the default state that generalization starts in, unless we're treating aliases as rigid.
368+
/// It also means we're not currently inside an alias, since then we change the state to
369+
/// `IncompletelyRelateAliasArgs`
361370
Default,
362-
IncompletelyRelateHigherRankedAlias,
363-
/// Only one layer
371+
/// We enter this state when we're generalizing the arguments of a potentially normalizeable alias.
372+
///
373+
/// The behavior here is different between the old and the new solver:
374+
///
375+
/// In the old solver, the difference between this and `Default` is needed to
376+
/// correctly handle `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`.
377+
/// That equality can hold by either normalizing the outer or the inner associated type.
378+
/// In the old solver, we always structurally relate aliases,
379+
/// however, when we encounter an occurs check failure, we propagate the failure to the outermost alias,
380+
/// for which we then emit a Projection goal.
381+
///
382+
/// In the new solver, we rarely get into this state.
383+
/// When we encounter aliases we instead attempt to normalize them, and treat them as rigid using `ShallowStructurallyRelate`.
384+
/// Only when an alias is higher-ranked, we continue with similar logic to the old solver,
385+
/// except now we also explicitly relate the type and consts in the arguments of aliases while in this mode.
386+
///
387+
/// FIXME: Because we relate the type and consts in the arguments of aliases while in this mode,
388+
/// this is "incomplete".
389+
IncompletelyRelateAliasArgs,
390+
/// During generalization, when we encounter aliases,
391+
/// we will first attempt to normalize them when we're using the next trait solver.
392+
/// We can now treat the normalized alias as rigid, but only for "one layer", hence shallow.
393+
/// New aliases encountered inside the arguments of the outer alias should once again be related as normal.
364394
ShallowStructurallyRelateAliases,
395+
/// Treat aliases as rigid when relating them.
396+
///
397+
/// This corresponds to `relation.structurally_relate_aliases()`.
365398
StructurallyRelateAliases,
366399
}
367400

@@ -400,11 +433,10 @@ struct Generalizer<'me, 'tcx> {
400433
/// some other type. What will be the variance at this point?
401434
ambient_variance: ty::Variance,
402435

403-
/// This is set once we're generalizing the arguments of an alias.
436+
/// This field keeps track of how we treat aliases during generalization.
404437
///
405-
/// This is necessary to correctly handle
406-
/// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
407-
/// hold by either normalizing the outer or the inner associated type.
438+
/// Refer to [`GeneralizerState`]'s docs for more information about the
439+
/// all the possible values this can have, and when we use which.
408440
state: GeneralizerState,
409441

410442
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, GeneralizerState), Ty<'tcx>>,
@@ -483,11 +515,11 @@ impl<'tcx> Generalizer<'_, 'tcx> {
483515

484516
return res;
485517
}
486-
GeneralizerState::Default | GeneralizerState::IncompletelyRelateHigherRankedAlias => {}
518+
GeneralizerState::Default | GeneralizerState::IncompletelyRelateAliasArgs => {}
487519
}
488520

489521
let previous_state =
490-
mem::replace(&mut self.state, GeneralizerState::IncompletelyRelateHigherRankedAlias);
522+
mem::replace(&mut self.state, GeneralizerState::IncompletelyRelateAliasArgs);
491523
let result = match self.relate(alias, alias) {
492524
Ok(alias) => Ok(alias.to_ty(self.cx())),
493525
Err(e) => match previous_state {
@@ -504,7 +536,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
504536
debug!("generalization failure in alias");
505537
Ok(self.next_ty_var_for_alias())
506538
}
507-
GeneralizerState::IncompletelyRelateHigherRankedAlias => return Err(e),
539+
GeneralizerState::IncompletelyRelateAliasArgs => return Err(e),
508540

509541
// Early return.
510542
GeneralizerState::ShallowStructurallyRelateAliases
@@ -613,6 +645,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
613645
// of each other. This is currently only used for diagnostics.
614646
// To see why, see the docs in the `type_variables` module.
615647
inner.type_variables().sub_unify(vid, new_var_id);
648+
616649
// If we're in the new solver and create a new inference
617650
// variable inside of an alias we eagerly constrain that
618651
// inference variable to prevent unexpected ambiguity errors.
@@ -632,13 +665,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
632665
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
633666
{
634667
match self.state {
635-
GeneralizerState::IncompletelyRelateHigherRankedAlias => {
668+
GeneralizerState::IncompletelyRelateAliasArgs => {
636669
inner.type_variables().equate(vid, new_var_id);
637670
}
671+
GeneralizerState::Default
672+
| GeneralizerState::ShallowStructurallyRelateAliases
673+
| GeneralizerState::StructurallyRelateAliases => {}
638674
}
639-
GeneralizerState::Default
640-
| GeneralizerState::ShallowStructurallyRelateAliases
641-
| GeneralizerState::StructurallyRelateAliases => {}
642675
}
643676

644677
debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
@@ -765,13 +798,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
765798
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
766799
{
767800
match self.state {
768-
GeneralizerState::IncompletelyRelateHigherRankedAlias => {
801+
GeneralizerState::IncompletelyRelateAliasArgs => {
769802
variable_table.union(vid, new_var_id);
770803
}
804+
GeneralizerState::Default
805+
| GeneralizerState::ShallowStructurallyRelateAliases
806+
| GeneralizerState::StructurallyRelateAliases => {}
771807
}
772-
GeneralizerState::Default
773-
| GeneralizerState::ShallowStructurallyRelateAliases
774-
| GeneralizerState::StructurallyRelateAliases => {}
775808
}
776809
Ok(ty::Const::new_var(self.cx(), new_var_id))
777810
}

compiler/rustc_middle/src/hooks/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,12 @@ declare_hooks! {
132132
) -> Ty<'tcx>;
133133
}
134134

135-
// `repr(transparent)` so we can transmute a `&'a Infcx<'tcx>` to this struct.
135+
/// The `try_eagerly_normalize_alias` hook passes an `Infcx` from where it's called (in `rustc_infer`)
136+
/// to where it's provided (in `rustc_trait_selection`).
137+
/// Both of those crates have that type available, but `rustc_middle` does not.
138+
/// Instead we pass this type-erased `Infcx` and transmute on both sides.
139+
///
140+
/// Has to be `repr(transparent)` so we can transmute a `&'a Infcx<'tcx>` to this struct.
136141
#[repr(transparent)]
137142
pub struct TypeErasedInfcx<'a, 'tcx> {
138143
_infcx: *const (),

compiler/rustc_trait_selection/src/solve.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ fn try_eagerly_normalize_alias<'a, 'tcx>(
5656
let cause = ObligationCause::dummy_with_span(span);
5757
let obligation = Obligation::new(
5858
tcx,
59-
// we ignore the error anyway
60-
ObligationCause::dummy_with_span(span),
59+
cause,
6160
param_env,
6261
ty::PredicateKind::AliasRelate(
6362
alias.to_ty(tcx).into(),
@@ -68,7 +67,8 @@ fn try_eagerly_normalize_alias<'a, 'tcx>(
6867

6968
ocx.register_obligation(obligation);
7069

71-
// This only tries to eagerly resolve, if it errors we don't care.
70+
// We only use this to constrain inference variables.
71+
// We don't care if it errors.
7272
let _ = ocx.try_evaluate_obligations();
7373

7474
infcx.resolve_vars_if_possible(infer_term)

tests/ui/impl-trait/unsized_coercion.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
44
//@ revisions: next old
55
//@[next] compile-flags: -Znext-solver
6-
//@[old] check-pass
7-
//@[next] check-pass
6+
//@ check-pass
87

98
trait Trait {}
109

0 commit comments

Comments
 (0)