diff options
Diffstat (limited to 'vendor/chalk-derive-0.80.0')
-rw-r--r-- | vendor/chalk-derive-0.80.0/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/chalk-derive-0.80.0/Cargo.toml | 36 | ||||
-rw-r--r-- | vendor/chalk-derive-0.80.0/README.md | 3 | ||||
-rw-r--r-- | vendor/chalk-derive-0.80.0/src/lib.rs | 305 |
4 files changed, 345 insertions, 0 deletions
diff --git a/vendor/chalk-derive-0.80.0/.cargo-checksum.json b/vendor/chalk-derive-0.80.0/.cargo-checksum.json new file mode 100644 index 000000000..8edc8025e --- /dev/null +++ b/vendor/chalk-derive-0.80.0/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"e3c3e60a45e0bf583d6806e3006106e7686207a1afeab12b723a966f0a2a2319","README.md":"41a362e6750d37202fcf0a87a0b48ae41552715d97d740ee9883424ebae78564","src/lib.rs":"47d7fad24f9aa6c2229ce43fb0846f343d0b1c345ba3f15f74d30acaf5c61a55"},"package":"d0001adf0cf12361e08b65e1898ea138f8f77d8f5177cbf29b6b3b3532252bd6"}
\ No newline at end of file diff --git a/vendor/chalk-derive-0.80.0/Cargo.toml b/vendor/chalk-derive-0.80.0/Cargo.toml new file mode 100644 index 000000000..27ef29c10 --- /dev/null +++ b/vendor/chalk-derive-0.80.0/Cargo.toml @@ -0,0 +1,36 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "chalk-derive" +version = "0.80.0" +authors = ["Rust Compiler Team", "Chalk developers"] +description = "A helper crate for use by chalk crates for `derive` macros." +readme = "README.md" +keywords = ["compiler", "traits", "prolog"] +license = "Apache-2.0/MIT" +repository = "https://github.com/rust-lang/chalk" + +[lib] +proc-macro = true +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "1.0" +features = ["full"] + +[dependencies.synstructure] +version = "0.12.5" diff --git a/vendor/chalk-derive-0.80.0/README.md b/vendor/chalk-derive-0.80.0/README.md new file mode 100644 index 000000000..43fa19a03 --- /dev/null +++ b/vendor/chalk-derive-0.80.0/README.md @@ -0,0 +1,3 @@ +A helper crate for use by chalk crates for `derive` macros. + +See [Github](https://github.com/rust-lang/chalk) for up-to-date information. diff --git a/vendor/chalk-derive-0.80.0/src/lib.rs b/vendor/chalk-derive-0.80.0/src/lib.rs new file mode 100644 index 000000000..99e602f21 --- /dev/null +++ b/vendor/chalk-derive-0.80.0/src/lib.rs @@ -0,0 +1,305 @@ +extern crate proc_macro; + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use quote::ToTokens; +use syn::{parse_quote, DeriveInput, GenericParam, Ident, TypeParamBound}; + +use synstructure::decl_derive; + +/// Checks whether a generic parameter has a `: HasInterner` bound +fn has_interner(param: &GenericParam) -> Option<&Ident> { + bounded_by_trait(param, "HasInterner") +} + +/// Checks whether a generic parameter has a `: Interner` bound +fn is_interner(param: &GenericParam) -> Option<&Ident> { + bounded_by_trait(param, "Interner") +} + +fn has_interner_attr(input: &DeriveInput) -> Option<TokenStream> { + Some( + input + .attrs + .iter() + .find(|a| a.path.is_ident("has_interner"))? + .parse_args::<TokenStream>() + .expect("Expected has_interner argument"), + ) +} + +fn bounded_by_trait<'p>(param: &'p GenericParam, name: &str) -> Option<&'p Ident> { + let name = Some(String::from(name)); + match param { + GenericParam::Type(ref t) => t.bounds.iter().find_map(|b| { + if let TypeParamBound::Trait(trait_bound) = b { + if trait_bound + .path + .segments + .last() + .map(|s| s.ident.to_string()) + == name + { + return Some(&t.ident); + } + } + None + }), + _ => None, + } +} + +fn get_generic_param(input: &DeriveInput) -> &GenericParam { + match input.generics.params.len() { + 1 => {} + + 0 => panic!( + "deriving this trait requires a single type parameter or a `#[has_interner]` attr" + ), + + _ => panic!("deriving this trait only works with a single type parameter"), + }; + &input.generics.params[0] +} + +fn get_generic_param_name(input: &DeriveInput) -> Option<&Ident> { + match get_generic_param(input) { + GenericParam::Type(t) => Some(&t.ident), + _ => None, + } +} + +fn find_interner(s: &mut synstructure::Structure) -> (TokenStream, DeriveKind) { + let input = s.ast(); + + if let Some(arg) = has_interner_attr(input) { + // Hardcoded interner: + // + // #[has_interner(ChalkIr)] + // struct S { + // + // } + return (arg, DeriveKind::FromHasInternerAttr); + } + + let generic_param0 = get_generic_param(input); + + if let Some(param) = has_interner(generic_param0) { + // HasInterner bound: + // + // Example: + // + // struct Binders<T: HasInterner> { } + s.add_impl_generic(parse_quote! { _I }); + + s.add_where_predicate(parse_quote! { _I: ::chalk_ir::interner::Interner }); + s.add_where_predicate( + parse_quote! { #param: ::chalk_ir::interner::HasInterner<Interner = _I> }, + ); + + (quote! { _I }, DeriveKind::FromHasInterner) + } else if let Some(i) = is_interner(generic_param0) { + // Interner bound: + // + // Example: + // + // struct Foo<I: Interner> { } + (quote! { #i }, DeriveKind::FromInterner) + } else { + panic!("deriving this trait requires a parameter that implements HasInterner or Interner",); + } +} + +#[derive(Copy, Clone, PartialEq)] +enum DeriveKind { + FromHasInternerAttr, + FromHasInterner, + FromInterner, +} + +decl_derive!([HasInterner, attributes(has_interner)] => derive_has_interner); +decl_derive!([Visit, attributes(has_interner)] => derive_visit); +decl_derive!([SuperVisit, attributes(has_interner)] => derive_super_visit); +decl_derive!([Fold, attributes(has_interner)] => derive_fold); +decl_derive!([Zip, attributes(has_interner)] => derive_zip); + +fn derive_has_interner(mut s: synstructure::Structure) -> TokenStream { + s.underscore_const(true); + let (interner, _) = find_interner(&mut s); + + s.add_bounds(synstructure::AddBounds::None); + s.bound_impl( + quote!(::chalk_ir::interner::HasInterner), + quote! { + type Interner = #interner; + }, + ) +} + +/// Derives Visit for structs and enums for which one of the following is true: +/// - It has a `#[has_interner(TheInterner)]` attribute +/// - There is a single parameter `T: HasInterner` (does not have to be named `T`) +/// - There is a single parameter `I: Interner` (does not have to be named `I`) +fn derive_visit(s: synstructure::Structure) -> TokenStream { + derive_any_visit(s, parse_quote! { Visit }, parse_quote! { visit_with }) +} + +/// Same as Visit, but derives SuperVisit instead +fn derive_super_visit(s: synstructure::Structure) -> TokenStream { + derive_any_visit( + s, + parse_quote! { SuperVisit }, + parse_quote! { super_visit_with }, + ) +} + +fn derive_any_visit( + mut s: synstructure::Structure, + trait_name: Ident, + method_name: Ident, +) -> TokenStream { + s.underscore_const(true); + let input = s.ast(); + let (interner, kind) = find_interner(&mut s); + + let body = s.each(|bi| { + quote! { + ::chalk_ir::try_break!(::chalk_ir::visit::Visit::visit_with(#bi, visitor, outer_binder)); + } + }); + + if kind == DeriveKind::FromHasInterner { + let param = get_generic_param_name(input).unwrap(); + s.add_where_predicate(parse_quote! { #param: ::chalk_ir::visit::Visit<#interner> }); + } + + s.add_bounds(synstructure::AddBounds::None); + s.bound_impl( + quote!(::chalk_ir::visit:: #trait_name <#interner>), + quote! { + fn #method_name <B>( + &self, + visitor: &mut dyn ::chalk_ir::visit::Visitor < #interner, BreakTy = B >, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> std::ops::ControlFlow<B> { + match *self { + #body + } + std::ops::ControlFlow::Continue(()) + } + }, + ) +} + +fn each_variant_pair<F, R>( + a: &mut synstructure::Structure, + b: &mut synstructure::Structure, + mut f: F, +) -> TokenStream +where + F: FnMut(&synstructure::VariantInfo<'_>, &synstructure::VariantInfo<'_>) -> R, + R: ToTokens, +{ + let mut t = TokenStream::new(); + for (v_a, v_b) in a.variants_mut().iter_mut().zip(b.variants_mut().iter_mut()) { + v_a.binding_name(|_, i| Ident::new(&format!("a_{}", i), Span::call_site())); + v_b.binding_name(|_, i| Ident::new(&format!("b_{}", i), Span::call_site())); + + let pat_a = v_a.pat(); + let pat_b = v_b.pat(); + let body = f(v_a, v_b); + + quote!((#pat_a, #pat_b) => {#body}).to_tokens(&mut t); + } + t +} + +fn derive_zip(mut s: synstructure::Structure) -> TokenStream { + s.underscore_const(true); + let (interner, _) = find_interner(&mut s); + + let mut a = s.clone(); + let mut b = s.clone(); + + let mut body = each_variant_pair(&mut a, &mut b, |v_a, v_b| { + let mut t = TokenStream::new(); + for (b_a, b_b) in v_a.bindings().iter().zip(v_b.bindings().iter()) { + quote!(chalk_ir::zip::Zip::zip_with(zipper, variance, #b_a, #b_b)?;).to_tokens(&mut t); + } + quote!(Ok(())).to_tokens(&mut t); + t + }); + + // when the two variants are different + quote!((_, _) => Err(::chalk_ir::NoSolution)).to_tokens(&mut body); + + s.add_bounds(synstructure::AddBounds::None); + s.bound_impl( + quote!(::chalk_ir::zip::Zip<#interner>), + quote! { + + fn zip_with<Z: ::chalk_ir::zip::Zipper<#interner>>( + zipper: &mut Z, + variance: ::chalk_ir::Variance, + a: &Self, + b: &Self, + ) -> ::chalk_ir::Fallible<()> { + match (a, b) { #body } + } + }, + ) +} + +/// Derives Fold for structs and enums for which one of the following is true: +/// - It has a `#[has_interner(TheInterner)]` attribute +/// - There is a single parameter `T: HasInterner` (does not have to be named `T`) +/// - There is a single parameter `I: Interner` (does not have to be named `I`) +fn derive_fold(mut s: synstructure::Structure) -> TokenStream { + s.underscore_const(true); + s.bind_with(|_| synstructure::BindStyle::Move); + + let (interner, kind) = find_interner(&mut s); + + let body = s.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|_, index| { + let bind = &bindings[index]; + quote! { + ::chalk_ir::fold::Fold::fold_with(#bind, folder, outer_binder)? + } + }) + }); + + let input = s.ast(); + let type_name = &input.ident; + + let result = if kind == DeriveKind::FromHasInterner { + let param = get_generic_param_name(input).unwrap(); + s.add_impl_generic(parse_quote! { _U }) + .add_where_predicate( + parse_quote! { #param: ::chalk_ir::fold::Fold<#interner, Result = _U> }, + ) + .add_where_predicate( + parse_quote! { _U: ::chalk_ir::interner::HasInterner<Interner = #interner> }, + ); + quote! { #type_name <_U> } + } else { + quote! { #type_name < #interner > } + }; + + s.add_bounds(synstructure::AddBounds::None); + s.bound_impl( + quote!(::chalk_ir::fold::Fold<#interner>), + quote! { + type Result = #result; + + fn fold_with<E>( + self, + folder: &mut dyn ::chalk_ir::fold::Folder < #interner, Error = E >, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::std::result::Result<Self::Result, E> { + Ok(match self { #body }) + } + }, + ) +} |