Skip to content

Commit d665c0b

Browse files
committed
address review
1 parent 9aa065b commit d665c0b

4 files changed

Lines changed: 65 additions & 23 deletions

File tree

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

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,51 @@ 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
368+
/// treating aliases as rigid. It also means we're not currently inside an
369+
/// alias, since then we change the state to `IncompletelyRelateAliasArgs`.
361370
Default,
362-
IncompletelyRelateHigherRankedAlias,
363-
/// Only one layer
371+
/// We enter this state when we're generalizing the arguments of a
372+
/// potentially normalizeable alias.
373+
///
374+
/// The behavior here is different between the old and the new solver:
375+
///
376+
/// In the old solver, the difference between this and `Default` is needed to
377+
/// correctly handle `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. That
378+
/// equality can hold by either normalizing the outer or the inner
379+
/// associated type. In the old solver, we always structurally relate
380+
/// aliases. If we we encounter an occurs check failure, we propagate the
381+
/// failure to the outermost alias, for which we then emit a `Projection`
382+
/// goal instead.
383+
///
384+
/// In the new solver, we rarely get into this state.
385+
/// When we encounter aliases we instead attempt to normalize them, and treat
386+
/// them as rigid using `ShallowStructurallyRelate`. Only when an alias has
387+
/// escaping bound variables do we continue with similar logic to the old
388+
/// solver, except now we also explicitly relate the type and consts in the
389+
/// arguments of aliases while in this mode.
390+
///
391+
/// FIXME: Because we relate the type and consts in the arguments of aliases
392+
/// while in this mode, this is incomplete.
393+
IncompletelyRelateAliasArgs,
394+
/// During generalization, when we encounter aliases, we will first attempt
395+
/// to normalize them when we're using the next trait solver. We can now
396+
/// treat the normalized alias as rigid, but only for "one layer", hence
397+
/// shallow. New aliases encountered inside the arguments of the outer alias
398+
/// should once again be related as normal.
364399
ShallowStructurallyRelateAliases,
400+
/// Treat aliases as rigid when relating them.
401+
///
402+
/// This corresponds to `relation.structurally_relate_aliases()`.
365403
StructurallyRelateAliases,
366404
}
367405

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

403-
/// This is set once we're generalizing the arguments of an alias.
441+
/// This field keeps track of how we treat aliases during generalization.
404442
///
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.
443+
/// Refer to [`GeneralizerState`]'s docs for more information about the
444+
/// all the possible values this can have, and when we use which.
408445
state: GeneralizerState,
409446

410447
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, GeneralizerState), Ty<'tcx>>,
@@ -483,11 +520,11 @@ impl<'tcx> Generalizer<'_, 'tcx> {
483520

484521
return res;
485522
}
486-
GeneralizerState::Default | GeneralizerState::IncompletelyRelateHigherRankedAlias => {}
523+
GeneralizerState::Default | GeneralizerState::IncompletelyRelateAliasArgs => {}
487524
}
488525

489526
let previous_state =
490-
mem::replace(&mut self.state, GeneralizerState::IncompletelyRelateHigherRankedAlias);
527+
mem::replace(&mut self.state, GeneralizerState::IncompletelyRelateAliasArgs);
491528
let result = match self.relate(alias, alias) {
492529
Ok(alias) => Ok(alias.to_ty(self.cx())),
493530
Err(e) => match previous_state {
@@ -504,7 +541,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
504541
debug!("generalization failure in alias");
505542
Ok(self.next_ty_var_for_alias())
506543
}
507-
GeneralizerState::IncompletelyRelateHigherRankedAlias => return Err(e),
544+
GeneralizerState::IncompletelyRelateAliasArgs => return Err(e),
508545

509546
// Early return.
510547
GeneralizerState::ShallowStructurallyRelateAliases
@@ -613,6 +650,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
613650
// of each other. This is currently only used for diagnostics.
614651
// To see why, see the docs in the `type_variables` module.
615652
inner.type_variables().sub_unify(vid, new_var_id);
653+
616654
// If we're in the new solver and create a new inference
617655
// variable inside of an alias we eagerly constrain that
618656
// inference variable to prevent unexpected ambiguity errors.
@@ -632,13 +670,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
632670
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
633671
{
634672
match self.state {
635-
GeneralizerState::IncompletelyRelateHigherRankedAlias => {
673+
GeneralizerState::IncompletelyRelateAliasArgs => {
636674
inner.type_variables().equate(vid, new_var_id);
637675
}
676+
GeneralizerState::Default
677+
| GeneralizerState::ShallowStructurallyRelateAliases
678+
| GeneralizerState::StructurallyRelateAliases => {}
638679
}
639-
GeneralizerState::Default
640-
| GeneralizerState::ShallowStructurallyRelateAliases
641-
| GeneralizerState::StructurallyRelateAliases => {}
642680
}
643681

644682
debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
@@ -765,13 +803,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
765803
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
766804
{
767805
match self.state {
768-
GeneralizerState::IncompletelyRelateHigherRankedAlias => {
806+
GeneralizerState::IncompletelyRelateAliasArgs => {
769807
variable_table.union(vid, new_var_id);
770808
}
809+
GeneralizerState::Default
810+
| GeneralizerState::ShallowStructurallyRelateAliases
811+
| GeneralizerState::StructurallyRelateAliases => {}
771812
}
772-
GeneralizerState::Default
773-
| GeneralizerState::ShallowStructurallyRelateAliases
774-
| GeneralizerState::StructurallyRelateAliases => {}
775813
}
776814
Ok(ty::Const::new_var(self.cx(), new_var_id))
777815
}

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)