Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::token::Comma;
use syn::{FieldValue, Ident, ItemImpl, ItemStruct, Type};

use crate::exports::{FinalizeBuild, IsPresent};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{field_to_member, field_value_expr, to_generic_args};

Expand Down Expand Up @@ -49,5 +50,7 @@ pub fn derive_finalize_build_impl(
}
};

Ok(item_impl)
// Key the error span on the struct name the user wrote, not the whole
// derive. See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::token::Comma;
use syn::{FieldValue, Ident, ItemImpl, ItemStruct};

use crate::exports::{HasBuilder, IsNothing};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{field_to_member, field_value_expr, to_generic_args};

Expand Down Expand Up @@ -44,5 +45,7 @@ pub fn derive_has_builder_impl(
}
};

Ok(item_impl)
// Key the error span on the struct name the user wrote, not the whole
// derive. See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use syn::spanned::Spanned;
use syn::{Ident, ItemImpl, ItemStruct};

use crate::exports::{HasField, IsPresent, MapType};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{
field_to_member, field_to_tag, index_to_generic_ident, to_generic_args,
Expand Down Expand Up @@ -55,7 +57,13 @@ pub fn derive_has_field_impls(
}
};

item_impls.push(item_impl);
// Point an error on this per-field impl at the field the user wrote
// rather than at the whole derive. See docs/implementation/README.md#spans.
let field_span = current_field
.ident
.as_ref()
.map_or_else(|| current_field.span(), |ident| ident.span());
item_impls.push(override_item_span(field_span, &item_impl)?);
}

Ok(item_impls)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::token::Comma;
use syn::{FieldValue, Ident, ItemImpl, ItemStruct};

use crate::exports::{IntoBuilder, IsPresent};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{field_to_member, field_value_expr, to_generic_args};

Expand Down Expand Up @@ -47,5 +48,7 @@ pub fn derive_into_builder_impl(
}
};

Ok(item_impl)
// Key the error span on the struct name the user wrote, not the whole
// derive. See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::{Ident, ItemImpl, ItemStruct};

use crate::exports::{MapType, PartialData};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::index_to_generic_ident;

Expand Down Expand Up @@ -32,5 +33,7 @@ pub fn derive_partial_data_impl_from_struct(
}
};

Ok(item_impl)
// Key the error span on the struct name the user wrote, not the whole
// derive. See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use quote::quote;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;
use syn::{FieldValue, GenericArgument, Ident, ItemImpl, ItemStruct, Type};

use crate::exports::{MapType, UpdateField};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{
field_to_member, field_to_tag, field_value_expr, index_to_generic_ident, to_generic_args,
Expand Down Expand Up @@ -99,7 +101,13 @@ pub fn derive_update_field_impls(
}
};

item_impls.push(item_impl);
// Point an error on this per-field impl at the field the user wrote
// rather than at the whole derive. See docs/implementation/README.md#spans.
let field_span = current_field
.ident
.as_ref()
.map_or_else(|| current_field.span(), |ident| ident.span());
item_impls.push(override_item_span(field_span, &item_impl)?);
}

Ok(item_impls)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::{Arm, GenericArgument, Ident, ItemEnum, ItemImpl, Type};

use crate::exports::{ExtractField, IsPresent, IsVoid, MapType, MapTypeRef};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{get_variant_type, index_to_generic_ident, to_generic_args};
use crate::types::field::Symbol;
Expand Down Expand Up @@ -116,7 +117,12 @@ pub fn derive_extract_field_impls(
}
};

item_impls.push(item_impl);
// Point an error on this per-variant impl at the variant the user wrote
// rather than at the whole derive. See docs/implementation/README.md#spans.
item_impls.push(override_item_span(
current_variant.ident.span(),
&item_impl,
)?);
}

Ok(item_impls)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::{Ident, ItemEnum, ItemImpl, Type};

use crate::exports::{FinalizeExtract, IsVoid, MapTypeRef};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::to_generic_args;

Expand Down Expand Up @@ -61,5 +62,7 @@ pub fn derive_finalize_extract_impl(
}
};

Ok(item_impl)
// Key the error span on the enum name the user wrote, not the whole derive.
// See docs/implementation/README.md#spans.
override_item_span(context_enum.ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use quote::quote;
use syn::{Arm, Ident, ItemEnum, ItemImpl};

use crate::exports::{HasExtractor, HasExtractorMut, HasExtractorRef, IsMut, IsPresent, IsRef};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::to_generic_args;

Expand Down Expand Up @@ -62,7 +63,9 @@ pub fn derive_has_extractor_impl(
}
};

Ok(item_impl)
// Key the error span on the enum name the user wrote, not the whole derive.
// See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}

/// Emit the `HasExtractorRef` impl over the borrowed partial enum (`IsRef`). Its
Expand Down Expand Up @@ -137,7 +140,9 @@ pub fn derive_has_extractor_ref_impl(
}
};

Ok(item_impl)
// Key the error span on the enum name the user wrote, not the whole derive.
// See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}

/// Emit the `HasExtractorMut` impl: the `IsMut` mirror of
Expand Down Expand Up @@ -209,5 +214,7 @@ pub fn derive_has_extractor_mut_impl(
}
};

Ok(item_impl)
// Key the error span on the enum name the user wrote, not the whole derive.
// See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::{Ident, ItemEnum, ItemImpl};

use crate::exports::{MapType, MapTypeRef, PartialData};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::index_to_generic_ident;

Expand Down Expand Up @@ -56,5 +57,7 @@ pub fn derive_partial_data_impl_from_enum(
}
};

Ok(item_impl)
// Key the error span on the enum name the user wrote, not the whole derive.
// See docs/implementation/README.md#spans.
override_item_span(context_ident.span(), &item_impl)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use syn::{ItemEnum, ItemImpl};

use crate::exports::FromVariant;
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::get_variant_type;
use crate::types::field::Symbol;
Expand Down Expand Up @@ -32,7 +33,11 @@ pub fn derive_from_variant_from_enum(item_enum: &ItemEnum) -> syn::Result<Vec<It
}
};

item_impls.push(item_impl);
// Aim a compiler error on this impl at the variant the user wrote rather
// than at the whole `#[derive(...)]`, which is where the impl's
// `call_site`-spanned boundary would otherwise put the caret. See
// docs/implementation/README.md#spans.
item_impls.push(override_item_span(variant_ident.span(), &item_impl)?);
}

Ok(item_impls)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use syn::spanned::Spanned;
use syn::{Fields, ItemImpl, ItemStruct, LitInt};

use crate::exports::{HasField, HasFieldMut};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::field::{Index, Symbol};

Expand All @@ -17,6 +18,14 @@ pub fn derive_has_field_impls_from_struct(item_struct: &ItemStruct) -> syn::Resu
for field in fields.named.iter() {
let field_ident = field.ident.as_ref().unwrap();

// Aim a compiler error on either generated impl — a coherence
// conflict (`E0119`) with a hand-written `HasField` impl for the
// same tag, say — at the field the user wrote rather than at the
// whole `#[derive(HasField)]`, which is where the impl's
// `call_site`-spanned `impl`/`{ … }` boundary would otherwise put
// the caret. See docs/implementation/README.md#spans.
let field_span = field_ident.span();

let field_symbol = Symbol::from_ident(field_ident.clone());

let field_type = &field.ty;
Expand Down Expand Up @@ -53,18 +62,23 @@ pub fn derive_has_field_impls_from_struct(item_struct: &ItemStruct) -> syn::Resu
}
};

item_impls.push(has_field_impl);
item_impls.push(has_field_mut_impl);
item_impls.push(override_item_span(field_span, &has_field_impl)?);
item_impls.push(override_item_span(field_span, &has_field_mut_impl)?);
}
}
Fields::Unnamed(fields) => {
for (i, field) in fields.unnamed.iter().enumerate() {
// A tuple field has no identifier, so its whole `syn::Field` span
// is the narrowest token the user wrote; re-span each generated
// impl onto it for the same reason as the named case above.
let field_span = field.span();

let field_tag = Index {
index: i,
span: field.span(),
span: field_span,
};

let field_ident = LitInt::new(&format!("{i}"), field.span());
let field_ident = LitInt::new(&format!("{i}"), field_span);

let field_type = &field.ty;

Expand Down Expand Up @@ -100,8 +114,8 @@ pub fn derive_has_field_impls_from_struct(item_struct: &ItemStruct) -> syn::Resu
}
};

item_impls.push(has_field_impl);
item_impls.push(has_field_mut_impl);
item_impls.push(override_item_span(field_span, &has_field_impl)?);
item_impls.push(override_item_span(field_span, &has_field_mut_impl)?);
}
}
_ => {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use quote::quote;
use syn::{ItemEnum, ItemImpl};

use crate::exports::{HasFields, HasFieldsRef};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{
derive_from_fields_for_enum, derive_to_fields_for_enum, derive_to_fields_ref_for_enum,
Expand Down Expand Up @@ -45,11 +46,17 @@ pub fn derive_has_fields_impls_from_enum(item_enum: &ItemEnum) -> syn::Result<Ve

let to_fields_ref_impl = derive_to_fields_ref_for_enum(item_enum)?;

Ok(vec![
// These impls are all keyed on the whole enum, so aim an error on any of
// their headers at the enum name the user wrote rather than at the whole
// `#[derive(...)]`. See docs/implementation/README.md#spans.
[
has_fields_impl,
has_fields_ref_impl,
from_fields_impl,
to_fields_impl,
to_fields_ref_impl,
])
]
.into_iter()
.map(|item_impl| override_item_span(struct_name.span(), &item_impl))
.collect()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use quote::quote;
use syn::{ItemImpl, ItemStruct};

use crate::exports::{HasFields, HasFieldsRef};
use crate::functions::override_item_span;
use crate::parse_internal;
use crate::types::cgp_data::{
derive_from_fields_for_struct, derive_to_fields_for_struct, derive_to_fields_ref_for_struct,
Expand Down Expand Up @@ -46,11 +47,17 @@ pub fn derive_has_fields_impls_from_struct(item_struct: &ItemStruct) -> syn::Res

let to_fields_ref_impl = derive_to_fields_ref_for_struct(item_struct)?;

Ok(vec![
// These impls are all keyed on the whole struct, so aim an error on any of
// their headers at the struct name the user wrote rather than at the whole
// `#[derive(...)]`. See docs/implementation/README.md#spans.
[
has_fields_impl,
has_fields_ref_impl,
from_fields_impl,
to_fields_impl,
to_fields_ref_impl,
])
]
.into_iter()
.map(|item_impl| override_item_span(struct_name.span(), &item_impl))
.collect()
}
Loading
Loading