Skip to content

Fix a "will be a hard error" warning + drive-by #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 24, 2019
Merged
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ rust:
- nightly
- beta
- stable
- 1.30.0

script:
- cargo build --verbose
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cssparser"
version = "0.25.4"
version = "0.25.5"
authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]

description = "Rust implementation of CSS Syntax Level 3"
Expand Down
9 changes: 6 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ mod codegen {
println!("cargo:rerun-if-changed={}", input.display());

// We have stack overflows on Servo's CI.
let handle = Builder::new().stack_size(128 * 1024 * 1024).spawn(move || {
match_byte::expand(&input, &output);
}).unwrap();
let handle = Builder::new()
.stack_size(128 * 1024 * 1024)
.spawn(move || {
match_byte::expand(&input, &output);
})
.unwrap();

handle.join().unwrap();
}
Expand Down
52 changes: 31 additions & 21 deletions build/match_byte.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ use syn::parse::{Parse, ParseStream, Result};

use proc_macro2::{Span, TokenStream};

struct MatchByteParser {
}
struct MatchByteParser {}

pub fn expand(from: &Path, to: &Path) {
let mut source = String::new();
File::open(from).unwrap().read_to_string(&mut source).unwrap();
File::open(from)
.unwrap()
.read_to_string(&mut source)
.unwrap();
let ast = syn::parse_file(&source).expect("Parsing rules.rs module");
let mut m = MatchByteParser {};
let ast = m.fold_file(ast);

let code = ast.into_token_stream().to_string().replace("{ ", "{\n").replace(" }", "\n}");
File::create(to).unwrap().write_all(code.as_bytes()).unwrap();
let code = ast
.into_token_stream()
.to_string()
.replace("{ ", "{\n")
.replace(" }", "\n}");
File::create(to)
.unwrap()
.write_all(code.as_bytes())
.unwrap();
}

struct MatchByte {
Expand All @@ -45,7 +54,7 @@ impl Parse for MatchByte {
arms.push(input.call(syn::Arm::parse)?);
}
arms
}
},
})
}
}
Expand All @@ -55,16 +64,14 @@ fn get_byte_from_expr_lit(expr: &Box<syn::Expr>) -> u8 {
syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => {
if let syn::Lit::Byte(ref byte) = *lit {
byte.value()
}
else {
} else {
panic!("Found a pattern that wasn't a byte")
}
},
}
_ => unreachable!(),
}
}


/// Expand a TokenStream corresponding to the `match_byte` macro.
///
/// ## Example
Expand Down Expand Up @@ -93,12 +100,12 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {

for pat in &arm.pats {
match pat {
&syn::Pat::Lit(syn::PatLit{ref expr}) => {
&syn::Pat::Lit(syn::PatLit { ref expr }) => {
let value = get_byte_from_expr_lit(expr);
if table[value as usize] == 0 {
table[value as usize] = case_id as u8;
}
},
}
&syn::Pat::Range(syn::PatRange { ref lo, ref hi, .. }) => {
let lo = get_byte_from_expr_lit(lo);
let hi = get_byte_from_expr_lit(hi);
Expand All @@ -110,14 +117,14 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
if table[hi as usize] == 0 {
table[hi as usize] = case_id as u8;
}
},
}
&syn::Pat::Wild(_) => {
for byte in table.iter_mut() {
if *byte == 0 {
*byte = case_id as u8;
}
}
},
}
&syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
assert_eq!(wildcard, None);
wildcard = Some(ident);
Expand All @@ -126,7 +133,7 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
*byte = case_id as u8;
}
}
},
}
_ => {
panic!("Unexpected pattern: {:?}. Buggy code ?", pat);
}
Expand Down Expand Up @@ -159,11 +166,14 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
impl Fold for MatchByteParser {
fn fold_stmt(&mut self, stmt: syn::Stmt) -> syn::Stmt {
match stmt {
syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro{ ref mac, .. })) => {
syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro { ref mac, .. })) => {
if mac.path == parse_quote!(match_byte) {
return syn::fold::fold_stmt(self, syn::Stmt::Expr(expand_match_byte(&mac.tts)))
return syn::fold::fold_stmt(
self,
syn::Stmt::Expr(expand_match_byte(&mac.tts)),
);
}
},
}
_ => {}
}

Expand All @@ -172,11 +182,11 @@ impl Fold for MatchByteParser {

fn fold_expr(&mut self, expr: syn::Expr) -> syn::Expr {
match expr {
syn::Expr::Macro(syn::ExprMacro{ ref mac, .. }) => {
syn::Expr::Macro(syn::ExprMacro { ref mac, .. }) => {
if mac.path == parse_quote!(match_byte) {
return syn::fold::fold_expr(self, expand_match_byte(&mac.tts))
return syn::fold::fold_expr(self, expand_match_byte(&mac.tts));
}
},
}
_ => {}
}

Expand Down
14 changes: 8 additions & 6 deletions macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[macro_use] extern crate procedural_masquerade;
#[macro_use]
extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use] extern crate quote;
#[macro_use]
extern crate quote;
extern crate syn;

#[allow(unused_imports)] use std::ascii::AsciiExt;
use proc_macro2::{TokenStream, TokenTree};
use quote::TokenStreamExt;
use std::iter;
use proc_macro2::{TokenStream, TokenTree};

define_proc_macros! {
/// Input: the arms of a `match` expression.
Expand Down Expand Up @@ -88,12 +89,13 @@ define_proc_macros! {
}
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
fn max_len<I: Iterator<Item = usize>>(lengths: I) -> String {
let max_length = lengths.max().expect("expected at least one string");
quote!( const MAX_LENGTH: usize = #max_length; ).to_string()
}

fn string_literal(token: &TokenTree) -> String {
let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect()).expect(&format!("expected string literal, got {:?}", token));
let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect())
.expect(&format!("expected string literal, got {:?}", token));
lit.value()
}
87 changes: 52 additions & 35 deletions procedural-masquerade/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,35 @@ macro_rules! define_proc_macros {
pub fn _extract_input(derive_input: &str) -> &str {
let mut input = derive_input;

for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{",
"Input", "=", "(0,", "stringify!", "("] {
for expected in &[
"#[allow(unused)]",
"enum",
"ProceduralMasqueradeDummyType",
"{",
"Input",
"=",
"(0,",
"stringify!",
"(",
] {
input = input.trim_start();
assert!(input.starts_with(expected),
"expected prefix {:?} not found in {:?}", expected, derive_input);
assert!(
input.starts_with(expected),
"expected prefix {:?} not found in {:?}",
expected,
derive_input
);
input = &input[expected.len()..];
}

for expected in [")", ").0,", "}"].iter().rev() {
input = input.trim_end();
assert!(input.ends_with(expected),
"expected suffix {:?} not found in {:?}", expected, derive_input);
assert!(
input.ends_with(expected),
"expected suffix {:?} not found in {:?}",
expected,
derive_input
);
let end = input.len() - expected.len();
input = &input[..end];
}
Expand All @@ -227,33 +244,33 @@ macro_rules! define_invoke_proc_macro {
#[doc(hidden)]
#[macro_export]
macro_rules! $macro_name {
($proc_macro_name: ident ! $paren: tt) => {
#[derive($proc_macro_name)]
#[allow(unused)]
enum ProceduralMasqueradeDummyType {
// The magic happens here.
//
// We use an `enum` with an explicit discriminant
// because that is the only case where a type definition
// can contain a (const) expression.
//
// `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
//
// By the time the `#[proc_macro_derive]` function
// implementing `#[derive($proc_macro_name)]` is called,
// `$paren` has already been replaced with the input of this inner macro,
// but `stringify!` has not been expanded yet.
//
// This how arbitrary tokens can be inserted
// in the input to the `#[proc_macro_derive]` function.
//
// Later, `stringify!(...)` is expanded into a string literal
// which is then ignored.
// Using `stringify!` enables passing arbitrary tokens
// rather than only what can be parsed as a const expression.
Input = (0, stringify! $paren ).0
}
}
}
}
($proc_macro_name: ident ! $paren: tt) => {
#[derive($proc_macro_name)]
#[allow(unused)]
enum ProceduralMasqueradeDummyType {
// The magic happens here.
//
// We use an `enum` with an explicit discriminant
// because that is the only case where a type definition
// can contain a (const) expression.
//
// `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
//
// By the time the `#[proc_macro_derive]` function
// implementing `#[derive($proc_macro_name)]` is called,
// `$paren` has already been replaced with the input of this inner macro,
// but `stringify!` has not been expanded yet.
//
// This how arbitrary tokens can be inserted
// in the input to the `#[proc_macro_derive]` function.
//
// Later, `stringify!(...)` is expanded into a string literal
// which is then ignored.
// Using `stringify!` enables passing arbitrary tokens
// rather than only what can be parsed as a const expression.
Input = (0, stringify! $paren ).0
}
}
}
};
}
Loading