Merge pull request #123 from dtolnay/btree

Provide repetition for BTreeSet
This commit is contained in:
David Tolnay
2019-07-27 17:20:17 -07:00
committed by GitHub
2 changed files with 56 additions and 39 deletions
+41 -39
View File
@@ -42,8 +42,10 @@ impl BitOr<HasIterator> for HasIterator {
/// whichever impl happens to be applicable. Calling that method repeatedly on
/// the returned value should be idempotent.
pub mod ext {
use super::RepInterp;
use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
use crate::ToTokens;
use std::collections::btree_set::{self, BTreeSet};
use std::slice;
/// Extension trait providing the `quote_into_iter` method on iterators.
@@ -73,62 +75,62 @@ pub mod ext {
impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
/// Extension trait providing the `quote_into_iter` method for types
/// convertable into slices.
///
/// NOTE: This is implemented manually, rather than by using a blanket impl
/// over `AsRef<[T]>` to reduce the chance of ambiguity conflicts with other
/// `quote_into_iter` methods from this module.
pub trait RepSliceExt {
type Item;
/// Extension trait providing the `quote_into_iter` method for types that
/// can be referenced as an iterator.
pub trait RepAsIteratorExt<'q> {
type Iter: Iterator;
fn as_slice(&self) -> &[Self::Item];
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
}
fn quote_into_iter(&self) -> (slice::Iter<Self::Item>, HasIter) {
(self.as_slice().iter(), HasIter)
impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T {
type Iter = T::Iter;
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
<T as RepAsIteratorExt>::quote_into_iter(*self)
}
}
impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a T {
type Item = T::Item;
impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T {
type Iter = T::Iter;
fn as_slice(&self) -> &[Self::Item] {
<T as RepSliceExt>::as_slice(*self)
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
<T as RepAsIteratorExt>::quote_into_iter(*self)
}
}
impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a mut T {
type Item = T::Item;
impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
type Iter = slice::Iter<'q, T>;
fn as_slice(&self) -> &[Self::Item] {
<T as RepSliceExt>::as_slice(*self)
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
(self.iter(), HasIter)
}
}
impl<T> RepSliceExt for [T] {
type Item = T;
impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
type Iter = slice::Iter<'q, T>;
fn as_slice(&self) -> &[Self::Item] {
self
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
(self.iter(), HasIter)
}
}
impl<T> RepSliceExt for Vec<T> {
type Item = T;
impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
type Iter = btree_set::Iter<'q, T>;
fn as_slice(&self) -> &[Self::Item] {
&self[..]
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
(self.iter(), HasIter)
}
}
macro_rules! array_rep_slice {
($($l:tt)*) => {
$(
impl<T> RepSliceExt for [T; $l] {
type Item = T;
impl<'q, T: 'q> RepAsIteratorExt<'q> for [T; $l] {
type Iter = slice::Iter<'q, T>;
fn as_slice(&self) -> &[Self::Item] {
&self[..]
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
(self.iter(), HasIter)
}
}
)*
@@ -139,6 +141,14 @@ pub mod ext {
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
);
impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
type Iter = T::Iter;
fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
self.0.quote_into_iter()
}
}
}
// Helper type used within interpolations to allow for repeated binding names.
@@ -156,14 +166,6 @@ impl<T> RepInterp<T> {
}
}
impl<T: ext::RepSliceExt> ext::RepSliceExt for RepInterp<T> {
type Item = T::Item;
fn as_slice(&self) -> &[Self::Item] {
self.0.as_slice()
}
}
impl<T: Iterator> Iterator for RepInterp<T> {
type Item = T::Item;
+15
View File
@@ -1,6 +1,7 @@
#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]
use std::borrow::Cow;
use std::collections::BTreeSet;
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, TokenStreamExt};
@@ -250,6 +251,20 @@ fn test_duplicate_name_repetition_no_copy() {
assert_eq!(expected, tokens.to_string());
}
#[test]
fn test_btreeset_repetition() {
let mut set = BTreeSet::new();
set.insert("a".to_owned());
set.insert("b".to_owned());
let tokens = quote! {
#(#set: #set),*
};
let expected = r#""a" : "a" , "b" : "b""#;
assert_eq!(expected, tokens.to_string());
}
#[test]
fn test_variable_name_conflict() {
// The implementation of `#(...),*` uses the variable `_i` but it should be