You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: lib.rs
    path of file: ./repos/moxie/illicit/macro/src
    
    the code of the file until where you have to start completion: //! Procedural macro support crate for the `illicit` crate.

extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro_error::{abort, abort_call_site, proc_macro_error};
use quote::quote;
use syn::{
    parse::Parser, parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned,
    Attribute, FnArg, ItemFn, Local, PatType, Stmt, Token, Type, TypeReference,
};

#[proc_macro_attribute]
#[proc_macro_error]
pub fn from_env(args: TokenStream, input: TokenStream) -> TokenStream {
    let mut input_fn: ItemFn = parse_macro_input!(input);

    let args = Punctuated::<FnArg, Token![,]>::parse_terminated.parse(args).unwrap();
    if args.is_empty() {
        abort_call_site!("must specify >=1 one argument");
    }

    let doc_prelude = "
# Environment Expectations

This function requires the f
    
fn bind_env_reference(arg: &PatType) -> ([Local; 2], Attribute) {
    let arg_span = arg.span();

    let ty = match &*arg.ty {
        Type::Reference(TypeReference { lifetime, mutability, elem, .. }) => {
            if mutability.is_some() {
                abort!(mutability.span(), "mutable references cannot be passed by environment");
            }

            if lifetime.is_some() {
                abort!(
                    lifetime.span(),
                    "cannot bind to concrete lifetimes for environment references"
                );
            }

            quote!(#elem)
        }

        ty => abort!(ty.span(), "arguments must be references"),
    };

    let name = *arg.pat.clone();
    let init_expr = parse_quote!(illicit::expect::<#ty>());
    let deref_expr = parse_quote!(&*#name);

    let shadowed = Local {
        attrs: vec![],
        let_token: Token![let](arg_span),
        pat: name.clone(),
        init: Some((Token![=](arg_span), Box::new(init_expr))),
        semi_token: Token![;](arg_span),
    };
    let derefd = Local {
        attrs: vec![],
        let_token: Token![let](arg_span),
        pat: name,
        init: Some((Token![=](arg_span), Box::new(deref_expr))),
        semi_token: Token![;](arg_span),
    };

    let ty_bullet = format!("* `{}`", ty);
    let doc_attr = parse_quote!(#[doc = #ty_bullet]);

    ([shadowed, derefd], doc_attr)
}