Skip to content

Commit

Permalink
Use a less pervasive workaround for rustc bug
Browse files Browse the repository at this point in the history
We still have to work around
rust-lang/rust#47941 until it gets fixed
upstream, but we can at least do it in a way that's less pervasive, and
will be easier to remove in the future.
  • Loading branch information
sgrif committed Feb 4, 2018
1 parent 486792a commit 0f6cca6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 37 deletions.
2 changes: 1 addition & 1 deletion diesel_derives2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ homepage = "https://diesel.rs"
repository = "https://github.com/diesel-rs/diesel/tree/master/diesel_derives"

[dependencies]
syn = { version = "0.12.11", features = ["full"] }
syn = { version = "0.12.11", features = ["full", "fold"] }
quote = "0.4"
clippy = { optional = true, version = "=0.0.185" }
proc-macro2 = "0.2.0"
Expand Down
67 changes: 31 additions & 36 deletions diesel_derives2/src/meta.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
use proc_macro2::Span;
use syn;
use syn::spanned::Spanned;
use syn::fold::Fold;

use diagnostic_shim::*;

pub struct MetaItem {
// Due to https://github.com/rust-lang/rust/issues/47941
// we can only ever get the span of the #, which is better than nothing
pound_span: Span,
meta: syn::Meta,
}

impl MetaItem {
pub fn all_with_name(attrs: &[syn::Attribute], name: &str) -> Vec<Self> {
attrs
.iter()
.filter_map(|attr| attr.interpret_meta().map(|m| (attr.pound_token.0[0], m)))
.filter(|&(_, ref m)| m.name() == name)
.map(|(pound_span, meta)| Self { pound_span, meta })
.filter_map(|attr| {
attr.interpret_meta()
.map(|m| FixSpan(attr.pound_token.0[0]).fold_meta(m))
})
.filter(|m| m.name() == name)
.map(|meta| Self { meta })
.collect()
}

Expand All @@ -27,7 +28,6 @@ impl MetaItem {

pub fn empty(name: &str) -> Self {
Self {
pound_span: Span::call_site(),
meta: syn::Meta::List(syn::MetaList {
ident: name.into(),
paren_token: Default::default(),
Expand Down Expand Up @@ -99,10 +99,7 @@ impl MetaItem {
use syn::Meta::*;

match self.meta {
Word(mut x) => {
x.span = self.span_or_pound_token(x.span);
Ok(x)
}
Word(x) => Ok(x),
_ => {
let meta = &self.meta;
Err(self.span().error(format!(
Expand All @@ -118,7 +115,7 @@ impl MetaItem {
use syn::Meta::*;

match self.meta {
List(ref list) => Ok(Nested(list.nested.iter(), self.pound_span)),
List(ref list) => Ok(Nested(list.nested.iter())),
_ => Err(self.span()
.error(format!("`{0}` must be in the form `{0}(...)`", self.name()))),
}
Expand All @@ -138,9 +135,7 @@ impl MetaItem {
}

pub fn ty_value(&self) -> Result<syn::Type, Diagnostic> {
let mut str = self.lit_str_value()?.clone();
// https://github.com/rust-lang/rust/issues/47941
str.span = self.span_or_pound_token(str.span);
let str = self.lit_str_value()?;
str.parse().map_err(|_| str.span.error("Invalid Rust type"))
}

Expand All @@ -167,33 +162,20 @@ impl MetaItem {
fn value_span(&self) -> Span {
use syn::Meta::*;

let s = match self.meta {
match self.meta {
Word(ident) => ident.span,
List(ref meta) => meta.nested.span(),
NameValue(ref meta) => meta.lit.span(),
};
self.span_or_pound_token(s)
}
}

pub fn span(&self) -> Span {
self.span_or_pound_token(self.meta.span())
}

/// If the given span is affected by
/// https://github.com/rust-lang/rust/issues/47941,
/// returns the span of the pound token
fn span_or_pound_token(&self, span: Span) -> Span {
let bad_span_debug = "Span(Span { lo: BytePos(0), hi: BytePos(0), ctxt: #0 })";
if format!("{:?}", span) == bad_span_debug {
self.pound_span
} else {
span
}
self.meta.span()
}
}

#[cfg_attr(rustfmt, rustfmt_skip)] // https://github.com/rust-lang-nursery/rustfmt/issues/2392
pub struct Nested<'a>(syn::punctuated::Iter<'a, syn::NestedMeta, Token![,]>, Span);
pub struct Nested<'a>(syn::punctuated::Iter<'a, syn::NestedMeta, Token![,]>);

impl<'a> Iterator for Nested<'a> {
type Item = MetaItem;
Expand All @@ -202,12 +184,25 @@ impl<'a> Iterator for Nested<'a> {
use syn::NestedMeta::*;

match self.0.next() {
Some(&Meta(ref item)) => Some(MetaItem {
pound_span: self.1,
meta: item.clone(),
}),
Some(&Meta(ref item)) => Some(MetaItem { meta: item.clone() }),
Some(_) => self.next(),
None => None,
}
}
}

/// If the given span is affected by
/// <https://github.com/rust-lang/rust/issues/47941>,
/// returns the span of the pound token
struct FixSpan(Span);

impl Fold for FixSpan {
fn fold_span(&mut self, span: Span) -> Span {
let bad_span_debug = "Span(Span { lo: BytePos(0), hi: BytePos(0), ctxt: #0 })";
if format!("{:?}", span) == bad_span_debug {
self.0
} else {
span
}
}
}

0 comments on commit 0f6cca6

Please sign in to comment.