owned this note
owned this note
Published
Linked with GitHub
## Meeting 2023-12-21
- <https://doc.rust-lang.org/std/iter/trait.Iterator.html>
```rust
/* Without flux-attrs (proc macro) */
#[flux::sig(fn(i32{v: v > 0}))]
fn foo(x: i32) {
}
/* With flux-attrs (proc macro) */
flux!(
fn foo(x: i32{v: v > 0}) { }
/* New ItemStruct parsing feature */
struct S {
f: i32{v: v > 0}
}
)
/* Rust language: Trait generics */
impl MyTrait<i32> for String { /* ... */ }
impl MyTrait<i64> for String { /* ... */ }
/* Rust language: Associated types (different from trait generics) */
trait MyTrait<T> {
type Assoc;
}
impl MyTrait for u32 {
type Assoc = String;
}
trait Iterator {
type Item;
/* ... */
}
/* `WhereClause` for associated type without flux-attrs */
#[flux::sig(
fn(it: T)
where T: Iterator<Item = i32{v: v > 0}>
)]
fn takes_iterator<T>(it: T)
where T: Iterator<Item = i32>
{
for x in it {
let y = x + 1;
}
}
fn test00() {
let v: Vec<i32> = vec![1, 2, 3];
takes_iterator(v.into_iter());
}
fn test00_bad() {
let v: Vec<&str> = vec!["hello", "world"];
takes_iterator(v.into_iter()); // this won't compile
}
/* Function returning a generic type (like `ParseStream::parse`) */
fn foo<T>(x: T) {}
fn baz<T>(x: i32) -> T { /* ... */ }
fn test() {
let x: i32 = baz(3);
}
/* `syn` examples */
trait Parse {
fn parse(input: ParseStream) -> Result<Self>;
}
#[derive(Debug)]
pub struct ItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub sig: Signature,
pub block: Block,
}
impl Parse for ItemFn {
fn parse(input: ParseStream) -> Result<Self> {
Ok(ItemFn {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
sig: input.parse()?,
block: input.parse()?,
})
}
}
impl Parse for Signature {
fn parse(input: ParseStream) -> Result<Self> {
let content;
let fn_token: Token![fn] = input.parse()?;
let ident = input.parse()?;
let mut generics: Generics = input.parse()?;
let paren_token = parenthesized!(content in input);
let inputs = content.parse_terminated(FnArg::parse, Token![,])?;
let output = input.parse()?;
generics.where_clause = input.parse()?;
let requires = parse_requires(input)?;
let ensures = parse_ensures(input)?;
Ok(Signature { fn_token, ident, generics, paren_token, inputs, output, requires, ensures })
}
}
impl Parse for ItemStruct {
fn parse(input: ParseStream) -> Result<Self> {
let mut attrs = input.call(Attribute::parse_outer)?;
flux_tool_attrs(&mut attrs, FLUX_ATTRS);
let vis = input.parse::<Visibility>()?;
let struct_token = input.parse::<Token![struct]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let refined_by = parse_opt_refined_by(input)?;
let (where_clause, fields, semi_token) = data_struct(input)?;
Ok(ItemStruct {
attrs,
vis,
struct_token,
ident,
generics: Generics { where_clause, ..generics },
refined_by,
fields,
semi_token,
})
}
}
/* In `syn`:
Generics
-> WhereClause
-> WherePredicate
-> PredicateType
-> TypeParamBound
-> TraitBound
-> Path */
pub struct Generics {
pub lt_token: Option<Token![<]>, // <
pub params: Punctuated<GenericParam, Token![,]>,
pub gt_token: Option<Token![>]>, // >
pub where_clause: Option<syn::WhereClause>, // where
}
pub struct WhereClause {
pub where_token: Token![where],
pub predicates: Punctuated<WherePredicate, Token![,]>,
}
pub enum WherePredicate {
/// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
Lifetime(syn::PredicateLifetime),
/// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
Type(PredicateType),
}
pub struct PredicateType {
/// Any lifetimes from a `for` binding
pub lifetimes: Option<syn::BoundLifetimes>,
/// The type being bounded
pub bounded_ty: syn::Type, // bounded_ty: bounds
pub colon_token: Token![:],
/// Trait and lifetime bounds (`Clone+Send+'static`+ Iterator<Item=i32>)
pub bounds: Punctuated<TypeParamBound, Token![+]>,
}
pub enum TypeParamBound {
Trait(TraitBound),
Lifetime(syn::Lifetime),
}
pub struct TraitBound {
pub paren_token: Option<token::Paren>,
pub modifier: syn::TraitBoundModifier,
/// The `for<'a>` in `for<'a> Foo<&'a T>`
pub lifetimes: Option<syn::BoundLifetimes>,
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>` Baz<A, B>::Foo<T>
pub path: Path,
}
/* where T: Clone+Send+Iterator<Item=i32>+'static
^ TraitBound ^ Lifetime
|___________________________________|
bounds: Punctuated<TypeParamBound, Token![+]>
|____________________________________________|
WhereClause */
```