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.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
lcnr nikomatsakis
2025-04-16
Opaque stuff is "done"
Dyn trait dispatch and async functions
dyn Trait
type for any traitdyn Trait: Trait
(niko would like to revise in future editions)dyn Trait
has inherent members for-> impl Trait
fn changed(&mut self) -> dyn Future<Output = ()>
.box
operator that, when used in this place, does the thing it should do<dyn Trait>::changed
what does have to change:
Fn
trait, theOutput
is currentlySized
Fn() -> T
RFC 1: "rudiments"
.box
and with some intrinsics insteadRFC 2: "box box box"
.box
is one example (the fundamental one)box struct Foo
– where it can be recursive and so forthbox async fn
– same dealenum Foo { box BigVariant(BigData), SmallVariant }
RFC 3: "dyn safety is dead, long live dyn safety"
dyn Trait
is always alloweddyn Trait
does not implementTrait
unlessdyn Trait: Trait
implimpl<T: Observe + ?Sized> Observe for &T
(but not in this case)impl<T: Observe + ?Sized> Observe for &mut T
impl<T: Observe + ?Sized> Observe for Box<T>
self
if your methodsso you would write something like this
example of associated types
dyn Trait<AssocI = ..>
, methodfoo
is accessible if==
)Self
afterwards, don't add methodemplacement intrinsic proposal a la lcnr
cycle semantics normalizes-to goal (info)
https://github.com/rust-lang/rust/pull/139900
crater run updates (info)
top 1000 is working !
post to the project goal!!!
2025-03-19
opaque types :3
two issues
need to support 'revealing' uses in the defining scope
need to also support defining in parent, revealing in closure
whenever u use an opaque in its defining scope in mir borrowck
infcx.opaque_type_storage
After MIR typeck, we've got storage full of opaque type uses
Compute region graph to check whether any of the opaque type uses have universal arguments rarw
These are defining!
Apply member constraints for them to constrain regions in hidden type, map them to the opaque type definition
Use that definition to check all other uses of the opaque. This uses type equality
end of MIR typeck, two uses:
opaque<'a> = &'?1 Foo
// from the returnopaque<'?2> = &'?3 Foo
// from the recursive calloapque<'a>
has a universal arg -> defining use'1 member ['a, 'static]
->'1 = 'a
for<'a> opaque<'a> = &'a Foo
opaque<'?2>
is revealing, check by using the definition from the defining use&'3 Foo == defining_use['a/'temp] = &'temp Foo
takeaways: u can't assume different scc -> different values
current algorithm
niko's sketch
things to be resolved
2025-03-12
currently moving
unstable impls
- 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 →module-private impls
module-private impls
types team lead, some ideas
power of refactoring and clarifying how we think about things
effects modeling and development
impl async Default for Type
,impl Default for Type
– don't particularly want thisimpl Default for Type
,impl const Default for Type
– what the heck this is weirdimpl (const) Default for Type
– one impl that can be const or not (and later… could be async)let x = Iterator::map(todo!(), infer);
Sized trait and edition migration
Sized
toconst Sized
T: ?Sized
toT: ValueSized
or whateverfn foo<T: Sized>() { bar::<T>() }
fn bar<T: Sized>() { const { size_of::<T>() } }
trait Sized { (const) fn size_of() -> usize; }
2025-02-26
#137314 – making unproductive cycles errors fixes rust-lang/trait-system-refactor-initiative#114
rust-lang/rust-trait-system-initiative#104
rust-lang/rust-trait-system-initiative#109 – rayon hangs
lazy norm issue:
where Ti: IntoIterator, Ti::IntoIter: Iterator
for T0…TnTi: Iterator
<Tj as IntoIterator>::IntoIter: Iterator
<Tj as IntoIterator>::IntoIter = Ti
for some Tjimpl<T: Iterator> IntoIterator for T
implTj: Iterator
<Tk as IntoIterator>::IntoIter: Iterator
<A as Iterator>::IntoIter
cannot equalB
becauseB
does not appear in thereA: Trait
with candidatesA::Assoc: Trait
->A::Assoc = A
normalize(A::Assoc) = ?
impl<T: Trait> Indir
A: Trait
cycle unproductive? = rigid(A::Assoc)
rigid(A::Assoc) = B
? -> failB::Assoc: Trait
->B::Assoc = A
normalize(B::Assoc)
useimpl<T: Trait> Indir
B: Trait
A::Assoc: Trait
->A::Assoc = B
normalize(A::Assoc)
useimpl<T: Trait> Indir
A: Trait
cycle unproductiveB::Assoc: Trait
->B::Assoc = B
normalize(B::Assoc)
useimpl<T: Trait> Indir
B: Trait
cycle unproductiveC::Assoc: Trait
->C::Assoc = B
normalize(C::Assoc)
useimpl<T: Trait> Indir
C: Trait
A::Assoc: Trait
->A::Assoc = C
normalize(A::Assoc)
useimpl<T: Trait> Indir
A: Trait
cycle unproductiveB::Assoc: Trait
->B::Assoc = C
normalize(B::Assoc)
useimpl<T: Trait> Indir
B: Trait
cycle unproductiveC::Assoc: Trait
->C::Assoc = C
normalize(C::Assoc)
useimpl<T: Trait> Indir
C: Trait
cycle unproductiveC::Assoc: Trait
->C::Assoc = A
normalize(C::Assoc)
useimpl<T: Trait> Indir
Question:
normalizes_to
vs having it just fail (and caller somehow decides to fallback to rigid), kind of the equivalent of having these two rules<X as Trait>::Assoc eq Z :- normalizes_to(<X as Trait>::Assoc, Y), Y eq Z
<X as Trait>::Assoc eq rigid(<X as Trait>::Assoc).
<T as Trait<?x>>::Assoc
normalizes-tou32
if?x: Copy
, otherwise rigidu32
2025-02-19
niko reads
questions
2025-01-29
Implied bounds
stability_feature_enabled(F)
where-clause…?where Platform: SupportsTargetFeatureX
2025-01-22
2025-01-15
lcnr discovered a TRAGEDY
require universal args
opaque<u8> = u8
, should this beopaque<T> = T
oropaque<T> = u8
?opaque<'static> = 'static
, as aboveopaque<'a, 'a> = 'a
, should this beopaque<'a, 'b> = 'a
oropaque<'a, 'b> = 'b
?does this mess with member constraint inference/closure requirement propagation
Lcnr proposal on how to "fix the source"
nikomatsakis concern from gll
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5351a85d676098047873ec1ea5aaec4d
2024-01-10
member constraints
defining use
Opaque<'a, 'b> = &'?x ()
: need to make sure?x member ['a, 'b, 'static]
needs to know the way
?x
is related to the choice regions:?x
is equal to one of the choice regions, just choose that one?x
is outlived by some choice which is "smaller" than all others, choose that onewhy we don't know how these things relate
The closure desugars to
The assignment equates
Opaque<'local2>
withInv<'local1>
. After region constraint propagation we getOpaque<'ext1> = Inv<'ext2>
. The member constraint'ext2 member ['ext1, 'static]
is ambiguous.We only know what to do once the caller requires that
'ext1
and'ext2
are the same. This requires information from the caller to propagate into the closure.Opaque<'local2> = &'local1 ()
with'ext1: local2
and'local1: 'ext2
Final member constraint
'local1 member ['local2, 'static]
Currently fails even outside of closures as
'local2
is not universalOpaque<'aext> = &'local1 ()
with'local1: 'ext2
member constraint
'local1 member ['aext, 'static]
need to propagate to callerneed to constrain
'local1
to some external regionconceivably
'local1
could be set tomin('aext, 'static)
actual example: https://github.com/kurnevsky/esxtool/blob/88538ca7c8e068b5e38d4b386eb1bf3d5cede3d0/src/mwscript/parser.rs#L186-L191
Conclusions
There are 3 "steps" that build on one another
exists<X> { .. }
solution to caller) so that we can transform'local member ['ext1, 'ext2]
to'exists3
where'exists3 member ['ext1, 'ext2]
'local1 member ['local2, ..]
to'exists1 member [all free things]
(where'local2 = 'exists2
)'exists2 member ['exists1]
(where'local1 = 'exists2
)'local member ['exta, 'b, 'static]
forbid universal regions from the closurecompute region constraints via type check
create SCCs, remove higher-ranked stuff
solve region constraints – creating a value for each SCC
independently:
2024-12-18
Ideas
Rotating hack-o-rama
maybe for all hands
why this structure?
Mentored on-call / office hours / interning / externing
2024-12-04
2024-11-27
status
onboarding folks
goals
*
disjunctive traits
2024-11-11
https://github.com/nikomatsakis/rusty-logic
https://github.com/nikomatsakis/rusty-logic/blob/main/doc/intro.md
https://github.com/nikomatsakis/rusty-logic/blob/main/doc/judgments.md
This version is "not quite" the problem:
This version shows the problem more clearly:
Want this to work
WF check on the impl is
A<Q..> = t where W
Q
W
t
meets bounds in traitFor this check to not be broken, you must not be able to alias-bounds of
A
fort
X: Bar
T: Foo<FooItem = U>
FooItem: Bar
inFoo
X = U
Worry, can we always fund a path
Niko's theory
(Bar T)
and we know(FooItem ?X) : Bar
(FooItem ?X) ~~> T
?(OtherTrait ?X T)
Trait T ?X
?X = U
because(Trait T U) \in \Gamma
2024-10-30
cycle semantics
How to handle alias bounds:
why no check on normalization:
imagine the "alias-bounds hold" check fails for
<T as Trait>::Assoc
here. We only ever normalize that alias inside offoo
, so instantiatingfoo
would not need to prove anything, causing post-mono errors.example
Three possible places to error:
T: Trait
Trait Definition X1
Later Modality X2
T: Trait
givenimpl<Q..> Trait for _ where WC_impl
…WC_impl
later(WC) => V: Bound
later(WC) => V: Bound
relies on the callee using the alias has to productively prove something about theWC
*
Later Modality X3
T: Trait
givenimpl<Q..> Trait for _ where WC_impl
…WC_impl
later(WC) => V: Bound
X
from the "later" box ifFV(X) subset P
Niko claims this variation feels like it has to be true, but why…
caller
finds an impl ofTrait
forV
and provesV: Trait
(there are none)Assoc<T>: Copy
productively, subject toT: Trait
P
based onT: Trait
callee
assumesU: Trait
callee
assumesU::Assoc<U>
isCopy
P[U/T]
P
was dependent onU: Trait
under the most lenient rules and our original motivating example
caller
finds an impl ofTrait
forV
and provesAssoc = SomeType: Copy
productively, subject toV: Trait
P = V::Assoc: Copy
which held becauseV: Trait
impliesV::Assoc: Copy
callee
assumesU: Trait
callee
assumesU::Assoc
isCopy
P
(with appropriate substitution)P
was dependent onU: Trait
we should read https://people.mpi-sws.org/~dreyer/tor/papers/wadler.pdf
mir formality
2024-10-23
possible project goals
implementable trait aliases
for users
Niko's goal is to enable the above pattern
Niko would like a way to guarantee Send for things and get a compilation error if not
Niko would like trait aliases to be equivalent to a pair of impls
T: A
is equivalent toT: B + C
A
is implementedX: Foo<Y>
is equivalent to … what?X: Send
and an error ifY: Ord
does not hold (for traits)X: Send, Y: Ord
(for trait aliases)A
is implementedPotentially introduces some kind of cycle. Elaboration doesn't terminate.
2024-10-18
*
2024-09-10
productive and not productive cycles
B is implemented if A is implemented
invariant:
true soundness criteria
impl
in the program4 non-productive cycles we currently have to deal with
https://hackmd.io/nwRk504pQQ2qUPr87HXkWQ
normalizes_to(Alias, Vec<Alias>)
equate(Vec<Alias>, Vec<Alias>)
productiveequate(Alias, Alias)
trivial identity: OKnormalizes_to(Alias, ?0)
equate(Vec<Alias>, ?0)
productive:?0 = Vec<?1>
[^2]equate(Alias, ?1)
normalizes_to(Alias, ?1)
productive cycle: OKwhat actually happens in rustc:
AliasRelate(Alias, Vec<Alias>)
NormalizesTo(Alias, ?fresh_infer)
?fresh_infer = Vec<Alias>
Vec<Alias>
withVec<Alias>
okAliasRelate(Alias, ?0)
NormalizesTo(Alias, ?fresh_infer)
?fresh_infer = Vec<Alias>
Vec<Alias>
with?0
. Instantiate?0
withVec<Alias>
which may normalizeAlias
, which would then result inAliasRelate(Alias, ?1)
which cycles (and errors)https://github.com/rust-lang/trait-system-refactor-initiative/issues/75 may be relevant
related: occurs check, why
Vec<Alias> = Alias
ok butVec<?0> = ?0
notimpl<T> From<T> for T
Have to rerun here because
normalizes_to
constrains an inference var, resulting in overflow at some point.normalizes_to(Alias, Alias2)
toAlias2
equate(Alias2, Alias2)
trivial identity: OK not actually- 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 →we can modify the details of how this is expanded, e.g., normalizes-to (when target is another alias) recursively expand
the doc: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?both
summary:
finite size is good, actually
We want some kind of "finite size" predicate that must be proven when you normalize…
What Niko is thinking
Fact:
How it could be Line IMPL that is at fault
AlphaWf(Option<T>) :-
T: Beta =>
Wf(T::Beta<Option<T>>::Alpha) :-
Option<T>: Alpha :-
AlphaWf(Option<T>)
– cycleActually this would make it an error on both IMPL and at USE. Is that ok?
2024-06-10
G :=
[] G
– G is true in all possible worldsmight be easier if we do
2024-04-11
Niko's time
20% slack
20% project goals
20% amazon overhead
10% async
10% lang team
20% trait solver stuff
20% understand genai
2024-03-08
trait Foo<T: Ord>: Bar + Baz
coinduction breakage: https://github.com/rust-lang/trait-system-refactor-initiative/issues/80
AGREE THAT
BIG UNKNOWNS
2023-06-09
AliasBound
(elaborated bounds), have to recheck when using impl, can assume when using where clausesRule for normalization
https://github.com/rust-lang/a-mir-formality/blob/ca14d9941244eefc472a24895515cc278244534f/crates/formality-prove/src/prove/prove_normalize.rs#L35-L48
example where proof objects or "recording used candidates" is difficult: https://github.com/lcnr/random-rust-snippets/issues/2
new solver dealing with alias bounds
<T as Trait>::Assoc: Send
ifT: Trait
is proven using param env or alias bound candidates.- 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 →negative impls meh
niko: what stops you from adding
impl Foo for u32
in future release? If you could do this…the overlap we get…
…this should work? Proving
F = &A, F: !FnPtr
should be possible.2023-05-26
PR to talk through: https://github.com/rust-lang/rust/pull/111881
for auto traits partial negative impls are very sus and forbidding them is nice
forall<T>
if(WC)
not { Vec<T>: !Foo }
exists<T>
if(T: Debug)
// <– environment has an inference variable in itVec<T>: !Foo
MyType<T>: Trait<U>
always applicableSimplifiedType
with identity substs (and trait args all all unique params), then we can have a quick hashmap lookup to check whether a trait is guaranteed to not be implementedimpl ?Foo
2023-05-05
very unhelpful notes
- 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 →2023-04-10
Item bounds for opaque types and soundness
https://github.com/rust-lang/rust/issues/109387
When is this "well formed" and what can we assume…
forall<T> { WC => H: Debug, WF(H) }
when we have
Ty<T>: Trait<T>
in the full example:
Proving
Ty<T>
is well-formed–T: Trait<T>
<T as Trait<T>>::Assoc: Default
<Ty<T> as Trait<T>>::Assoc: Default
Conclusion:
normalize(O => Hidden)
can write a pass post borrowck which checks opaques being able to normalize them and without assuming
WF(O)
.Question: what about multiple
uniquifying lifetimes
<?0 as Trait<'a>>::Assoc == <?0 as Trait<'a>>::Assoc
exists<T, '0, '1> <T as Trait<'0>>::Assoc == <T as Trait<'1>>::Assoc
'0 == '1
=> non trivial2023-03-24
Niko's proposal for a topic:
lcnr's proposal for a topic:
2023-03-17
lcnr: "alias bounds"
https://github.com/lcnr/solver-woes/issues/9#issuecomment-1456284249
nikomatsakis: a-mir-formality update
https://github.com/nikomatsakis/a-mir-formality/blob/75ae1aaf323e36caa789db0edadce0886cd51721/crates/formality-prove/src/prove/prove_wc.rs#L46-L57
Example:
{} => {u32: PartialEq}
where it's not true :)impl Eq for u32
// suppose here is noimpl PartialEq for u32
{} => {u32: PartialEq}
where it IS trueimpl Eq for u32
// suppose here is noimpl PartialEq for u32
forall T. {T: Eq} => {T: PartialEq}
2023-02-13
2023-01-26
region stuff: https://hackmd.io/DiPJDUCFS4CN-9LI4l2W4A?view#Region-obligations-leak-check
u32: Trait<'a, 'b> where 'a: 'b
i32: Trait<'a, 'b>
if we ask
for<'a, 'b> _: Trait<'a, 'b>
niko's hackmd
https://hackmd.io/jqiadXq4SJ67DhjQqUFnew
2022-12-20
Coinduction and things
2022-06-30
cases where it might be nice to discuss
2022-06-02
annoying
Relate
: https://github.com/rust-lang/rust/blob/9598b4b594c97dff66feb93522e22db500deea07/compiler/rustc_middle/src/ty/relate.rs#L718-L724elaborate lattice.
my concern wrt suppression
Requirement:
dyn Foo<X = ...>
dyn Foo<X = ...>: Foo<X = ...>
must holddyn Foo<X = ...>: Foo
<– will fail for all the bad cases we have identified so far<dyn Foo<X = ...> as Foo>::X = ...
dyn Foo<X = ...>: Foo<X = ...>
must holdhttps://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b7b533af61d452da7edec4c619a07bdb
current state is that somehow we detect that
dyn Trait<Assoc2 = ...>: Trait
does not satisfy the super bound:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=10590d62d211b378c16fafe69d3bb80e
but
Conclusions:
dyn Foo
for ANY trait or trait bounds Foo, and you don't have to list all associated types eitherdyn Foo: Foo
which also checks thatFoo
"fully holds" (including where clauses)Foo
available as inherent methods ofdyn Foo
so long as they meet some criteria<dyn Foo as Foo>::len(x)
dyn Foo: Foo
doesn't hold, need inherent method2022-05-26
HashMap<TypeId, ...>
iter_component<T: IsInQuery>
whereIsInQuery
means that theTypeId
is in the hashmap.Related case:
Space of solutions:
T <: U
andU <: T
TypeId
is partialTypeId
…?2022-05-19
Placeholder
toUniversal
t-types MCPshould error:
should not:
We have
UserTy:
&'a u32
inferred_ty
&'static u32
(current) replaced with ``&'?x u32input:
&'static u32`UserTy == inferred_ty
inferred_ty :> input
2022-04-28
-Zdump-mir=nll
and-Zverbose
apply_requirements
: error happens in parent function but constraint is from closure2022-03-24
submitted https://github.com/rust-lang/rust/issues/95272
the outlives gets added here pernosco
which seems a bit fragile because it looks to be specialzed to
TyFnDef
…?const generics
https://github.com/rust-lang/project-const-generics/issues/43
https://github.com/rust-lang/project-const-generics/issues/37
2022-03-03
for later #94057
this one now https://github.com/rust-lang/rust/pull/93856
https://github.com/rust-lang/rust/issues/25860
implied bounds for
in
:'b: 'a
.implied bounds for
out
:'static: 'static
outlives during unification:
'static: 'a
,'static: 'b
,'c: 'b
,'a: 'static
to prove: assuming
'static: 'a
,'static: 'b
,'c: 'b
,'a: 'static
,'static: 'static
, does'b: 'a
hold?Can't prove that -> error!
for<P_L...> T_L <: for<P_R...> T_R
forall P_R. exists P_L. T_L <: T_R
for<P_L...> if (I_L) T_L <: for<P_R...> if(I_R) T_R
forall P_R. exists P_L. if(I_L) T_L <: if(I_R) T_R
if(I_L) T_L <: if(I_R) T_R
ifT_L <: T_R
I_R => I_L
or the other way around <– not doing this todayimplied bounds for
in
:'b: 'a
implied bounds for
out
:'b: 'b
outlives during unification:
'b: 'a'
, … –> ok2022-02-10
simplify_type
: https://github.com/rust-lang/rust/pull/92721Today in the compiler:
why implication types?
early vs late bound
In Rust type system, we get:
we could do this
not quite backwards compatible. No way to have turbofish, plus today this works:
in fact, with today's language, no way to specify T explicitly, must give arguments of valid type, e.g.
Implied bounds, how to think about it
Covariance in ret type bad
2022-02-03
2022-01-20
auto traits: https://github.com/rust-lang/rust/pull/85048
const generics shiny future
Regarding generic constants
We kind of already have them
how is that different from
Similarly
why not const fn
Initial proposal…
Niko proposed extending with
typechecking anon consts: https://github.com/rust-lang/rust/issues/79356
from
convert
2022-01-13
prove that
T: Trait
holdsT: Trait
andT: OtherTrait
Under the min_generic_const_exprs proposal, after name resolution, we can classify all legal generic constant as:
Interesting design questions that remain
fn foo<const N: usize>()
allowfoo<_>()
const ADD<const N: usize, const M: usize> = N + M
:Add<N, 1>
vsAdd<1, N>
.Niko wants:
shuffle(x, 2)
notshuffle::<2>(x)
lcnr is working on polymorphization (!)
A
andB
A
a polymorphic version ofB
current bug: check if
foo::<T, for<'a> fn(&'a ())>
is a polymorphic parent offoo::<i32, fn(&'erased ())>
for<> fn(foo::<T, for<'a> fn(&'a ())>)
for<'a> fn(foo::<i32, fn(&'a ())>)
current bug:
check if
foo::<'erased, 'erased>
is a polymorphic parent offoo::<'erased, 'erased>
for<'a, 'b> fn(foo::<'a, 'b>)
for<'a, 'b> fn(foo::<'a, 'b>)
from https://gist.github.com/nikomatsakis/8bfda6c1119727e13ec6e98f33d2b696
idea:
'erased
a fresh lifetime in that binder2022-01-11
min_generic_const_exprs
: https://hackmd.io/utjHsFL8SWSu98kYfF99uQT::Assoc
to<T as Foo<'b>>::Assoc
, side-stepping the problem2021-08-18
2021-07-21
Brainstorm of an idea
https://github.com/rust-lang/project-const-generics/blob/master/design-docs/anon-const-substs.md#unused-substs
could plausibly "remove"
U
from the list of generics and replaceT: SomeTrait<U>
withexists<U> { T: SomeTrait<U> }
.T::CONSTANT
might still be resolvable.