or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
projection normalizes-to mismatch
previous doc: https://hackmd.io/noGGefTfQ0eCARFb3D0tJw
Projection
in the environment is treated solely asnormalizes-to
. We useProjection
bounds to normalize without checking whether theterm
is equal to the associated type. As a goal,Projection
can be fulfilled usingalias-eq
. This means thatProjection
as an assumption is stronger than what we need to prove when it's used as a requirement.possible solutions
I believe the only way to solve this in a reasonable timeframe is by actually splitting
Projection
goals andNormalizesTo
.The question is: how do we prove
Projection
goals in this case:Projection
triesnormalizes-to
and useseq
if it failsThis is the behavior of the old solver. It's a bit of a mess for multiple reasons:
normalizes-to
is ambiguous, we have to detect whether the inference var is still unconstrained or not. If the inference var is still unconstrained, we must not bubble up any inference constraints as we may later want to fall back toeq
.eq
. Callingeq
would just end up atalias-relate
. At this point the next alternative may be betterProjection
directly equates the typeswell, this causes a fun issue
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →a minimized version:
impls_trait<?0>
requires provingProjection(<?0 as Trait>::Assoc, ?0)
, equating the projection and the inference variable results in an occurs check failure. This requires some changes to generalization.Another issue which is more frequent due to
Projection
now simply equating types:This test now triggers the "unstable query result" warning. We start with
Projection(<?0 as Trait<&'1>::Assoc, ?2)
, this returnsYES: ?1 = <?0 as Trait<&'1>::Assoc
, reprovingProjection(<?0 as Trait<&'1>::Assoc, <?0 as Trait<&'1>::Assoc)
requiresProjection(<?0 as Trait<&'1>::Assoc, <?0 as Trait<&'2>::Assoc)
due to uniquification, which is ambiguous.generalization uwu
Generalization is generally broken when dealing with aliases and higher ranked types[1].
The issues with with generalizating aliases can mostly be summarized as: generalizing an inference variable to an alias is pretty much always wrong as it does not consider the option to first normalize the alias instead. It is also broken if the projection contains bound variables, which we should delay until later.
A minimal fix
Inside of the generalizer, stop generalizing projections, replace them with inference variables. When relating an inference variable with a projection directly, generalize, if there is an occurs check failure, emit a
NormalizesTo
goal instead.This is not a great fix:
?x == Alias<<?x as ToUnit>::Assoc
. We would be able to constrain?x
toAlias<()>
here.notes from 2023-10-23
Adding to this issue
?x
could be set tofor<'a> fn(<T as Trait<'a>>::Assoc)
which would thenpass the occurs check and equate successfully.
We must not replace
<<?x as OtherTrait>::Assoc as Trait<'a>>::Assoc
with an inference variable as that variable is unable to name'a
.how Niko expects the "theoretically perfect" rules to look is that you can normalize at any point, kind of like this…
In cases where normalization fails, we could make the solver return "P = Q if P = Q", which effectively means "ambiguous normalization". When proving a binder, if the returned goals include
'a
, then we can return that the binder must be equal.Ideally we show that the "best" path through those rules above is to always normalize as much as we can (sound/complete)
for<'a> fn(&'a ()) <: ?0
sets?0
tofor<'a> fn(&'a ())
even though it could also befn(&'whatever ())
. ↩︎