Skip to content

Commit 8a69e14

Browse files
authored
Avoid copying Span when evaluating validation rules (#1242)
1 parent f213d51 commit 8a69e14

File tree

8 files changed

+115
-70
lines changed

8 files changed

+115
-70
lines changed

juniper/src/validation/multi_visitor.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
parser::Spanning,
77
validation::{ValidatorContext, Visitor},
88
value::ScalarValue,
9+
Span,
910
};
1011

1112
#[doc(hidden)]
@@ -177,54 +178,62 @@ where
177178
self.1.exit_inline_fragment(ctx, f);
178179
}
179180

180-
fn enter_null_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: Spanning<()>) {
181+
fn enter_null_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: SpannedInput<'a, ()>) {
181182
self.0.enter_null_value(ctx, n);
182183
self.1.enter_null_value(ctx, n);
183184
}
184-
fn exit_null_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: Spanning<()>) {
185+
fn exit_null_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: SpannedInput<'a, ()>) {
185186
self.0.exit_null_value(ctx, n);
186187
self.1.exit_null_value(ctx, n);
187188
}
188189

189-
fn enter_scalar_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: Spanning<&'a S>) {
190+
fn enter_scalar_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: SpannedInput<'a, S>) {
190191
self.0.enter_scalar_value(ctx, n);
191192
self.1.enter_scalar_value(ctx, n);
192193
}
193-
fn exit_scalar_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: Spanning<&'a S>) {
194+
fn exit_scalar_value(&mut self, ctx: &mut ValidatorContext<'a, S>, n: SpannedInput<'a, S>) {
194195
self.0.exit_scalar_value(ctx, n);
195196
self.1.exit_scalar_value(ctx, n);
196197
}
197198

198-
fn enter_enum_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: Spanning<&'a String>) {
199+
fn enter_enum_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: SpannedInput<'a, String>) {
199200
self.0.enter_enum_value(ctx, s);
200201
self.1.enter_enum_value(ctx, s);
201202
}
202-
fn exit_enum_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: Spanning<&'a String>) {
203+
fn exit_enum_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: SpannedInput<'a, String>) {
203204
self.0.exit_enum_value(ctx, s);
204205
self.1.exit_enum_value(ctx, s);
205206
}
206207

207-
fn enter_variable_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: Spanning<&'a String>) {
208+
fn enter_variable_value(
209+
&mut self,
210+
ctx: &mut ValidatorContext<'a, S>,
211+
s: SpannedInput<'a, String>,
212+
) {
208213
self.0.enter_variable_value(ctx, s);
209214
self.1.enter_variable_value(ctx, s);
210215
}
211-
fn exit_variable_value(&mut self, ctx: &mut ValidatorContext<'a, S>, s: Spanning<&'a String>) {
216+
fn exit_variable_value(
217+
&mut self,
218+
ctx: &mut ValidatorContext<'a, S>,
219+
s: SpannedInput<'a, String>,
220+
) {
212221
self.0.exit_variable_value(ctx, s);
213222
self.1.exit_variable_value(ctx, s);
214223
}
215224

216225
fn enter_list_value(
217226
&mut self,
218227
ctx: &mut ValidatorContext<'a, S>,
219-
l: Spanning<&'a Vec<Spanning<InputValue<S>>>>,
228+
l: SpannedInput<'a, Vec<Spanning<InputValue<S>>>>,
220229
) {
221230
self.0.enter_list_value(ctx, l);
222231
self.1.enter_list_value(ctx, l);
223232
}
224233
fn exit_list_value(
225234
&mut self,
226235
ctx: &mut ValidatorContext<'a, S>,
227-
l: Spanning<&'a Vec<Spanning<InputValue<S>>>>,
236+
l: SpannedInput<'a, Vec<Spanning<InputValue<S>>>>,
228237
) {
229238
self.0.exit_list_value(ctx, l);
230239
self.1.exit_list_value(ctx, l);
@@ -242,19 +251,20 @@ where
242251
fn enter_object_field(
243252
&mut self,
244253
ctx: &mut ValidatorContext<'a, S>,
245-
f: &'a (Spanning<String>, Spanning<InputValue<S>>),
254+
f: (SpannedInput<'a, String>, SpannedInput<'a, InputValue<S>>),
246255
) {
247256
self.0.enter_object_field(ctx, f);
248257
self.1.enter_object_field(ctx, f);
249258
}
250259
fn exit_object_field(
251260
&mut self,
252261
ctx: &mut ValidatorContext<'a, S>,
253-
f: &'a (Spanning<String>, Spanning<InputValue<S>>),
262+
f: (SpannedInput<'a, String>, SpannedInput<'a, InputValue<S>>),
254263
) {
255264
self.0.exit_object_field(ctx, f);
256265
self.1.exit_object_field(ctx, f);
257266
}
258267
}
259268

260-
type SpannedObject<'a, S> = Spanning<&'a Vec<(Spanning<String>, Spanning<InputValue<S>>)>>;
269+
type SpannedInput<'a, T> = Spanning<&'a T, &'a Span>;
270+
type SpannedObject<'a, S> = SpannedInput<'a, Vec<(Spanning<String>, Spanning<InputValue<S>>)>>;

juniper/src/validation/rules/no_fragment_cycles.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
parser::Spanning,
66
validation::{RuleError, ValidatorContext, Visitor},
77
value::ScalarValue,
8+
Span,
89
};
910

1011
pub fn factory<'a>() -> NoFragmentCycles<'a> {
@@ -15,9 +16,11 @@ pub fn factory<'a>() -> NoFragmentCycles<'a> {
1516
}
1617
}
1718

19+
type BorrowedSpanning<'a, T> = Spanning<&'a T, &'a Span>;
20+
1821
pub struct NoFragmentCycles<'a> {
1922
current_fragment: Option<&'a str>,
20-
spreads: HashMap<&'a str, Vec<Spanning<&'a str>>>,
23+
spreads: HashMap<&'a str, Vec<BorrowedSpanning<'a, str>>>,
2124
fragment_order: Vec<&'a str>,
2225
}
2326

@@ -73,16 +76,23 @@ where
7376
self.spreads
7477
.entry(current_fragment)
7578
.or_default()
76-
.push(Spanning::new(spread.span, spread.item.name.item));
79+
.push(BorrowedSpanning {
80+
item: spread.item.name.item,
81+
span: &spread.span,
82+
});
7783
}
7884
}
7985
}
8086

81-
type CycleDetectorState<'a> = (&'a str, Vec<&'a Spanning<&'a str>>, HashMap<&'a str, usize>);
87+
type CycleDetectorState<'a> = (
88+
&'a str,
89+
Vec<&'a BorrowedSpanning<'a, str>>,
90+
HashMap<&'a str, usize>,
91+
);
8292

8393
struct CycleDetector<'a> {
8494
visited: HashSet<&'a str>,
85-
spreads: &'a HashMap<&'a str, Vec<Spanning<&'a str>>>,
95+
spreads: &'a HashMap<&'a str, Vec<BorrowedSpanning<'a, str>>>,
8696
errors: Vec<RuleError>,
8797
}
8898

@@ -103,7 +113,7 @@ impl<'a> CycleDetector<'a> {
103113
fn detect_from_inner(
104114
&mut self,
105115
from: &'a str,
106-
path: Vec<&'a Spanning<&'a str>>,
116+
path: Vec<&'a BorrowedSpanning<'a, str>>,
107117
mut path_indices: HashMap<&'a str, usize>,
108118
) -> Vec<CycleDetectorState<'a>> {
109119
self.visited.insert(from);

juniper/src/validation/rules/no_undefined_variables.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
parser::{SourcePosition, Spanning},
44
validation::{RuleError, ValidatorContext, Visitor},
55
value::ScalarValue,
6+
Span,
67
};
78
use std::collections::{HashMap, HashSet};
89

@@ -21,9 +22,11 @@ pub fn factory<'a>() -> NoUndefinedVariables<'a> {
2122
}
2223
}
2324

25+
type BorrowedSpanning<'a, T> = Spanning<&'a T, &'a Span>;
26+
2427
pub struct NoUndefinedVariables<'a> {
2528
defined_variables: HashMap<Option<&'a str>, (SourcePosition, HashSet<&'a str>)>,
26-
used_variables: HashMap<Scope<'a>, Vec<Spanning<&'a str>>>,
29+
used_variables: HashMap<Scope<'a>, Vec<BorrowedSpanning<'a, str>>>,
2730
current_scope: Option<Scope<'a>>,
2831
spreads: HashMap<Scope<'a>, Vec<&'a str>>,
2932
}
@@ -33,7 +36,7 @@ impl<'a> NoUndefinedVariables<'a> {
3336
&'a self,
3437
scope: &Scope<'a>,
3538
defined: &HashSet<&'a str>,
36-
unused: &mut Vec<&'a Spanning<&'a str>>,
39+
unused: &mut Vec<BorrowedSpanning<'a, str>>,
3740
visited: &mut HashSet<Scope<'a>>,
3841
) {
3942
let mut to_visit = Vec::new();
@@ -59,7 +62,7 @@ impl<'a> NoUndefinedVariables<'a> {
5962
&'a self,
6063
scope: &Scope<'a>,
6164
defined: &HashSet<&'a str>,
62-
unused: &mut Vec<&'a Spanning<&'a str>>,
65+
unused: &mut Vec<BorrowedSpanning<'a, str>>,
6366
visited: &mut HashSet<Scope<'a>>,
6467
) -> Option<&'a Vec<&'a str>> {
6568
if visited.contains(scope) {
@@ -71,7 +74,7 @@ impl<'a> NoUndefinedVariables<'a> {
7174
if let Some(used_vars) = self.used_variables.get(scope) {
7275
for var in used_vars {
7376
if !defined.contains(&var.item) {
74-
unused.push(var);
77+
unused.push(*var);
7578
}
7679
}
7780
}
@@ -164,7 +167,10 @@ where
164167
.item
165168
.referenced_variables()
166169
.iter()
167-
.map(|&var_name| Spanning::new(value.span, var_name))
170+
.map(|&var_name| BorrowedSpanning {
171+
span: &value.span,
172+
item: var_name,
173+
})
168174
.collect(),
169175
);
170176
}

juniper/src/validation/rules/no_unused_fragments.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
parser::Spanning,
66
validation::{ValidatorContext, Visitor},
77
value::ScalarValue,
8+
Span,
89
};
910

1011
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -21,9 +22,11 @@ pub fn factory<'a>() -> NoUnusedFragments<'a> {
2122
}
2223
}
2324

25+
type BorrowedSpanning<'a, T> = Spanning<&'a T, &'a Span>;
26+
2427
pub struct NoUnusedFragments<'a> {
2528
spreads: HashMap<Scope<'a>, Vec<&'a str>>,
26-
defined_fragments: HashSet<Spanning<&'a str>>,
29+
defined_fragments: HashSet<BorrowedSpanning<'a, str>>,
2730
current_scope: Option<Scope<'a>>,
2831
}
2932

@@ -100,8 +103,10 @@ where
100103
f: &'a Spanning<Fragment<S>>,
101104
) {
102105
self.current_scope = Some(Scope::Fragment(f.item.name.item));
103-
self.defined_fragments
104-
.insert(Spanning::new(f.span, f.item.name.item));
106+
self.defined_fragments.insert(BorrowedSpanning {
107+
span: &f.span,
108+
item: f.item.name.item,
109+
});
105110
}
106111

107112
fn enter_fragment_spread(

juniper/src/validation/rules/unique_input_field_names.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
parser::{SourcePosition, Spanning},
66
validation::{ValidatorContext, Visitor},
77
value::ScalarValue,
8+
Span,
89
};
910

1011
pub struct UniqueInputFieldNames<'a> {
@@ -32,13 +33,13 @@ where
3233
fn enter_object_field(
3334
&mut self,
3435
ctx: &mut ValidatorContext<'a, S>,
35-
(field_name, _): &'a (Spanning<String>, Spanning<InputValue<S>>),
36+
(field_name, _): (SpannedInput<'a, String>, SpannedInput<InputValue<S>>),
3637
) {
3738
if let Some(ref mut known_names) = self.known_name_stack.last_mut() {
38-
match known_names.entry(&field_name.item) {
39+
match known_names.entry(field_name.item) {
3940
Entry::Occupied(e) => {
4041
ctx.report_error(
41-
&error_message(&field_name.item),
42+
&error_message(field_name.item),
4243
&[*e.get(), field_name.span.start],
4344
);
4445
}
@@ -50,7 +51,8 @@ where
5051
}
5152
}
5253

53-
type SpannedObject<'a, S> = Spanning<&'a Vec<(Spanning<String>, Spanning<InputValue<S>>)>>;
54+
type SpannedInput<'a, T> = Spanning<&'a T, &'a Span>;
55+
type SpannedObject<'a, S> = SpannedInput<'a, Vec<(Spanning<String>, Spanning<InputValue<S>>)>>;
5456

5557
fn error_message(field_name: &str) -> String {
5658
format!("There can only be one input field named \"{field_name}\"")

juniper/src/validation/rules/variables_in_allowed_position.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
parser::Spanning,
1010
validation::{ValidatorContext, Visitor},
1111
value::ScalarValue,
12+
Span,
1213
};
1314

1415
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -28,7 +29,7 @@ pub fn factory<'a, S: fmt::Debug>() -> VariableInAllowedPosition<'a, S> {
2829

2930
pub struct VariableInAllowedPosition<'a, S: fmt::Debug + 'a> {
3031
spreads: HashMap<Scope<'a>, HashSet<&'a str>>,
31-
variable_usages: HashMap<Scope<'a>, Vec<(Spanning<&'a String>, Type<'a>)>>,
32+
variable_usages: HashMap<Scope<'a>, Vec<(SpannedInput<'a, String>, Type<'a>)>>,
3233
#[allow(clippy::type_complexity)]
3334
variable_defs: HashMap<Scope<'a>, Vec<&'a (Spanning<&'a str>, VariableDefinition<'a, S>)>>,
3435
current_scope: Option<Scope<'a>>,
@@ -160,18 +161,15 @@ where
160161
fn enter_variable_value(
161162
&mut self,
162163
ctx: &mut ValidatorContext<'a, S>,
163-
var_name: Spanning<&'a String>,
164+
var_name: SpannedInput<'a, String>,
164165
) {
165166
if let (Some(scope), Some(input_type)) =
166167
(&self.current_scope, ctx.current_input_type_literal())
167168
{
168169
self.variable_usages
169170
.entry(scope.clone())
170171
.or_default()
171-
.push((
172-
Spanning::new(var_name.span, var_name.item),
173-
input_type.clone(),
174-
));
172+
.push((var_name, input_type.clone()));
175173
}
176174
}
177175
}
@@ -186,6 +184,8 @@ fn error_message(
186184
)
187185
}
188186

187+
type SpannedInput<'a, T> = Spanning<&'a T, &'a Span>;
188+
189189
#[cfg(test)]
190190
mod tests {
191191
use super::{error_message, factory};

0 commit comments

Comments
 (0)