Merge pull request #2230 from LaurentMazare/master

More refactoring around boolean expression suggestion.
This commit is contained in:
Oliver Schneider 2017-11-20 09:26:22 +01:00 committed by GitHub
commit 80c9803bdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 124 additions and 173 deletions

View File

@ -159,120 +159,114 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
}
}
fn simplify_not(expr: &Expr, cx: &LateContext) -> Option<String> {
let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros");
match expr.node {
ExprBinary(binop, ref lhs, ref rhs) => {
match binop.node {
BiEq => Some(" != "),
BiNe => Some(" == "),
BiLt => Some(" >= "),
BiGt => Some(" <= "),
BiLe => Some(" > "),
BiGe => Some(" < "),
_ => None,
}.map(|op| format!("{}{}{}", &snip(lhs), op, &snip(rhs)))
},
ExprMethodCall(ref path, _, ref args) if args.len() == 1 => {
METHODS_WITH_NEGATION
.iter().cloned()
.flat_map(|(a, b)| vec![(a, b), (b, a)])
.find(|&(a, _)| a == path.name.as_str())
.map(|(_, neg_method)| format!("{}.{}()", &snip(&args[0]), neg_method))
},
_ => None,
struct SuggestContext<'a, 'tcx: 'a, 'v> {
terminals: &'v [&'v Expr],
cx: &'a LateContext<'a, 'tcx>,
output: String,
simplified: bool,
}
impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
fn snip(&self, e: &Expr) -> String {
snippet_opt(self.cx, e.span).expect("don't try to improve booleans created by macros")
}
fn simplify_not(&self, expr: &Expr) -> Option<String> {
match expr.node {
ExprBinary(binop, ref lhs, ref rhs) => {
match binop.node {
BiEq => Some(" != "),
BiNe => Some(" == "),
BiLt => Some(" >= "),
BiGt => Some(" <= "),
BiLe => Some(" > "),
BiGe => Some(" < "),
_ => None,
}.map(|op| format!("{}{}{}", self.snip(lhs), op, self.snip(rhs)))
},
ExprMethodCall(ref path, _, ref args) if args.len() == 1 => {
METHODS_WITH_NEGATION
.iter().cloned()
.flat_map(|(a, b)| vec![(a, b), (b, a)])
.find(|&(a, _)| a == path.name.as_str())
.map(|(_, neg_method)| format!("{}.{}()", self.snip(&args[0]), neg_method))
},
_ => None,
}
}
fn recurse(&mut self, suggestion: &Bool) {
use quine_mc_cluskey::Bool::*;
match *suggestion {
True => {
self.output.push_str("true");
},
False => {
self.output.push_str("false");
},
Not(ref inner) => match **inner {
And(_) | Or(_) => {
self.output.push('!');
self.output.push('(');
self.recurse(inner);
self.output.push(')');
},
Term(n) => {
let terminal = self.terminals[n as usize];
if let Some(str) = self.simplify_not(terminal) {
self.simplified = true;
self.output.push_str(&str)
} else {
self.output.push('!');
let snip = self.snip(terminal);
self.output.push_str(&snip);
}
},
True | False | Not(_) => {
self.output.push('!');
self.recurse(inner)
},
},
And(ref v) => {
for (index, inner) in v.iter().enumerate() {
if index > 0 {
self.output.push_str(" && ");
}
if let Or(_) = *inner {
self.output.push('(');
self.recurse(inner);
self.output.push(')');
} else {
self.recurse(inner);
}
}
},
Or(ref v) => {
for (index, inner) in v.iter().enumerate() {
if index > 0 {
self.output.push_str(" || ");
}
self.recurse(inner);
}
},
Term(n) => {
let snip = self.snip(self.terminals[n as usize]);
self.output.push_str(&snip);
},
}
}
}
// The boolean part of the return indicates whether some simplifications have been applied.
fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) {
fn recurse(
brackets: bool,
cx: &LateContext,
suggestion: &Bool,
terminals: &[&Expr],
s: &mut String,
simplified: &mut bool,
) {
use quine_mc_cluskey::Bool::*;
let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros");
match *suggestion {
True => {
s.push_str("true");
},
False => {
s.push_str("false");
},
Not(ref inner) => match **inner {
And(_) | Or(_) => {
s.push('!');
recurse(true, cx, inner, terminals, s, simplified)
},
Term(n) => {
if let Some(str) = simplify_not(terminals[n as usize], cx) {
*simplified = true;
s.push_str(&str)
} else {
s.push('!');
recurse(false, cx, inner, terminals, s, simplified)
}
},
True | False | Not(_) => {
s.push('!');
recurse(false, cx, inner, terminals, s, simplified)
},
},
And(ref v) => {
if brackets {
s.push('(');
}
for (index, inner) in v.iter().enumerate() {
if index > 0 {
s.push_str(" && ");
}
if let Or(_) = *inner {
recurse(true, cx, inner, terminals, s, simplified);
} else {
recurse(false, cx, inner, terminals, s, simplified);
}
}
if brackets {
s.push(')');
}
},
Or(ref v) => {
if brackets {
s.push('(');
}
for (index, inner) in v.iter().enumerate() {
if index > 0 {
s.push_str(" || ");
}
recurse(false, cx, inner, terminals, s, simplified);
}
if brackets {
s.push(')');
}
},
Term(n) => {
let brackets = brackets && match terminals[n as usize].node {
ExprBinary(..) => true,
_ => false,
};
if brackets {
s.push('(');
}
s.push_str(&snip(terminals[n as usize]));
if brackets {
s.push(')');
}
},
}
}
let mut simplified = false;
let mut s = String::new();
recurse(false, cx, suggestion, terminals, &mut s, &mut simplified);
(s, simplified)
let mut suggest_context = SuggestContext {
terminals: terminals,
cx: cx,
output: String::new(),
simplified: false,
};
suggest_context.recurse(suggestion);
(suggest_context.output, suggest_context.simplified)
}
fn simple_negate(b: Bool) -> Bool {

View File

@ -53,4 +53,7 @@ fn methods_with_negation() {
let _ = !b.is_ok();
let c = false;
let _ = !(a.is_some() && !c);
let _ = !(!c ^ c) || !a.is_some();
let _ = (!c ^ c) || !a.is_some();
let _ = !c ^ c || !a.is_some();
}

View File

@ -72,7 +72,6 @@ error: this boolean expression can be simplified
|
34 | let _ = a == b && c == 5 && a == b;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: try
|
34 | let _ = a == b && c == 5;
@ -85,7 +84,6 @@ error: this boolean expression can be simplified
|
35 | let _ = a == b && c == 5 && b == a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: try
|
35 | let _ = a == b && c == 5;
@ -122,7 +120,6 @@ error: this boolean expression can be simplified
|
39 | let _ = a != b || !(a != b || c == d);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: try
|
39 | let _ = c != d || a != b;
@ -160,3 +157,21 @@ error: this boolean expression can be simplified
55 | let _ = !(a.is_some() && !c);
| ^^^^^^^^^^^^^^^^^^^^ help: try: `c || a.is_none()`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:56:13
|
56 | let _ = !(!c ^ c) || !a.is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!(!c ^ c) || a.is_none()`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:57:13
|
57 | let _ = (!c ^ c) || !a.is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!c ^ c) || a.is_none()`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:58:13
|
58 | let _ = !c ^ c || !a.is_some();
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `!c ^ c || a.is_none()`

View File

@ -25,7 +25,6 @@ error: this if statement can be collapsed
17 | | }
18 | | }
| |_____^
|
help: try
|
14 | if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
@ -42,7 +41,6 @@ error: this if statement can be collapsed
23 | | }
24 | | }
| |_____^
|
help: try
|
20 | if x == "hello" && x == "world" && (y == "world" || y == "hello") {
@ -59,7 +57,6 @@ error: this if statement can be collapsed
29 | | }
30 | | }
| |_____^
|
help: try
|
26 | if (x == "hello" || x == "world") && y == "world" && y == "hello" {
@ -76,7 +73,6 @@ error: this if statement can be collapsed
35 | | }
36 | | }
| |_____^
|
help: try
|
32 | if x == "hello" && x == "world" && y == "world" && y == "hello" {
@ -93,7 +89,6 @@ error: this if statement can be collapsed
41 | | }
42 | | }
| |_____^
|
help: try
|
38 | if 42 == 1337 && 'a' != 'A' {
@ -111,7 +106,6 @@ error: this `else { if .. }` block can be collapsed
50 | | }
51 | | }
| |_____^
|
help: try
|
47 | } else if y == "world" {
@ -129,7 +123,6 @@ error: this `else { if .. }` block can be collapsed
58 | | }
59 | | }
| |_____^
|
help: try
|
55 | } else if let Some(42) = Some(42) {
@ -149,7 +142,6 @@ error: this `else { if .. }` block can be collapsed
69 | | }
70 | | }
| |_____^
|
help: try
|
63 | } else if y == "world" {
@ -172,7 +164,6 @@ error: this `else { if .. }` block can be collapsed
80 | | }
81 | | }
| |_____^
|
help: try
|
74 | } else if let Some(42) = Some(42) {
@ -195,7 +186,6 @@ error: this `else { if .. }` block can be collapsed
91 | | }
92 | | }
| |_____^
|
help: try
|
85 | } else if let Some(42) = Some(42) {
@ -218,7 +208,6 @@ error: this `else { if .. }` block can be collapsed
102 | | }
103 | | }
| |_____^
|
help: try
|
96 | } else if x == "hello" {
@ -241,7 +230,6 @@ error: this `else { if .. }` block can be collapsed
113 | | }
114 | | }
| |_____^
|
help: try
|
107 | } else if let Some(42) = Some(42) {

View File

@ -91,7 +91,6 @@ error: the loop variable `i` is only used to index `vec`.
96 | | let _ = vec[i];
97 | | }
| |_____^
|
help: consider using an iterator
|
95 | for <item> in &vec {
@ -104,7 +103,6 @@ error: the loop variable `j` is only used to index `STATIC`.
101 | | println!("{:?}", STATIC[j]);
102 | | }
| |_____^
|
help: consider using an iterator
|
100 | for <item> in STATIC.iter().take(4) {
@ -117,7 +115,6 @@ error: the loop variable `j` is only used to index `CONST`.
105 | | println!("{:?}", CONST[j]);
106 | | }
| |_____^
|
help: consider using an iterator
|
104 | for <item> in CONST.iter().take(4) {
@ -130,7 +127,6 @@ error: the loop variable `i` is used to index `vec`
109 | | println!("{} {}", vec[i], i);
110 | | }
| |_____^
|
help: consider using an iterator
|
108 | for (i, <item>) in vec.iter().enumerate() {
@ -143,7 +139,6 @@ error: the loop variable `i` is only used to index `vec2`.
117 | | println!("{}", vec2[i]);
118 | | }
| |_____^
|
help: consider using an iterator
|
116 | for <item> in vec2.iter().take(vec.len()) {
@ -156,7 +151,6 @@ error: the loop variable `i` is only used to index `vec`.
121 | | println!("{}", vec[i]);
122 | | }
| |_____^
|
help: consider using an iterator
|
120 | for <item> in vec.iter().skip(5) {
@ -169,7 +163,6 @@ error: the loop variable `i` is only used to index `vec`.
125 | | println!("{}", vec[i]);
126 | | }
| |_____^
|
help: consider using an iterator
|
124 | for <item> in vec.iter().take(MAX_LEN) {
@ -182,7 +175,6 @@ error: the loop variable `i` is only used to index `vec`.
129 | | println!("{}", vec[i]);
130 | | }
| |_____^
|
help: consider using an iterator
|
128 | for <item> in vec.iter().take(MAX_LEN + 1) {
@ -195,7 +187,6 @@ error: the loop variable `i` is only used to index `vec`.
133 | | println!("{}", vec[i]);
134 | | }
| |_____^
|
help: consider using an iterator
|
132 | for <item> in vec.iter().take(10).skip(5) {
@ -208,7 +199,6 @@ error: the loop variable `i` is only used to index `vec`.
137 | | println!("{}", vec[i]);
138 | | }
| |_____^
|
help: consider using an iterator
|
136 | for <item> in vec.iter().take(10 + 1).skip(5) {
@ -221,7 +211,6 @@ error: the loop variable `i` is used to index `vec`
141 | | println!("{} {}", vec[i], i);
142 | | }
| |_____^
|
help: consider using an iterator
|
140 | for (i, <item>) in vec.iter().enumerate().skip(5) {
@ -234,7 +223,6 @@ error: the loop variable `i` is used to index `vec`
145 | | println!("{} {}", vec[i], i);
146 | | }
| |_____^
|
help: consider using an iterator
|
144 | for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
@ -261,7 +249,6 @@ error: this range is empty so this for loop will never run
153 | | println!("{}", i);
154 | | }
| |_____^
|
help: consider using the following if you are attempting to iterate over this range in reverse
|
152 | for i in (0...10).rev() {
@ -274,7 +261,6 @@ error: this range is empty so this for loop will never run
157 | | println!("{}", i);
158 | | }
| |_____^
|
help: consider using the following if you are attempting to iterate over this range in reverse
|
156 | for i in (0..MAX_LEN).rev() {
@ -295,7 +281,6 @@ error: this range is empty so this for loop will never run
186 | | println!("{}", i);
187 | | }
| |_____^
|
help: consider using the following if you are attempting to iterate over this range in reverse
|
185 | for i in (5 + 4..10).rev() {
@ -308,7 +293,6 @@ error: this range is empty so this for loop will never run
190 | | println!("{}", i);
191 | | }
| |_____^
|
help: consider using the following if you are attempting to iterate over this range in reverse
|
189 | for i in ((3 - 1)..(5 + 2)).rev() {
@ -460,7 +444,6 @@ error: you seem to want to iterate on a map's values
394 | | // `in *m.values()` as we used to
395 | | }
| |_____^
|
help: use the corresponding method
|
390 | for v in (*m).values() {
@ -473,7 +456,6 @@ error: you seem to want to iterate on a map's values
399 | | let _v = v;
400 | | }
| |_____^
|
help: use the corresponding method
|
398 | for v in m.values_mut() {
@ -486,7 +468,6 @@ error: you seem to want to iterate on a map's values
404 | | let _v = v;
405 | | }
| |_____^
|
help: use the corresponding method
|
403 | for v in (*m).values_mut() {
@ -499,7 +480,6 @@ error: you seem to want to iterate on a map's keys
410 | | let _k = k;
411 | | }
| |_____^
|
help: use the corresponding method
|
409 | for k in rm.keys() {
@ -555,7 +535,6 @@ error: it looks like you're manually copying between slices
497 | | dst2[i + 500] = src[i]
498 | | }
| |_____^
|
help: try replacing the loop by
|
495 | dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)])

View File

@ -19,7 +19,6 @@ error: impl for `HashMap` should be generalized over different hashers
|
20 | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
| ^^^^^^^^^^^^^
|
help: consider adding a type parameter
|
20 | impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for (HashMap<K, V, S>,) {
@ -34,7 +33,6 @@ error: impl for `HashMap` should be generalized over different hashers
|
25 | impl Foo<i16> for HashMap<String, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider adding a type parameter
|
25 | impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashMap<String, String, S> {
@ -49,7 +47,6 @@ error: impl for `HashSet` should be generalized over different hashers
|
43 | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
| ^^^^^^^^^^
|
help: consider adding a type parameter
|
43 | impl<T: Hash + Eq, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashSet<T, S> {
@ -64,7 +61,6 @@ error: impl for `HashSet` should be generalized over different hashers
|
48 | impl Foo<i16> for HashSet<String> {
| ^^^^^^^^^^^^^^^
|
help: consider adding a type parameter
|
48 | impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashSet<String, S> {
@ -79,7 +75,6 @@ error: parameter of type `HashMap` should be generalized over different hashers
|
65 | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {
| ^^^^^^^^^^^^^^^^^
|
help: consider adding a type parameter
|
65 | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {
@ -90,7 +85,6 @@ error: parameter of type `HashSet` should be generalized over different hashers
|
65 | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {
| ^^^^^^^^^^^^
|
help: consider adding a type parameter
|
65 | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {
@ -104,7 +98,6 @@ error: impl for `HashMap` should be generalized over different hashers
...
83 | gen!(impl);
| ----------- in this macro invocation
|
help: consider adding a type parameter
|
70 | impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u8> for HashMap<K, V, S> {
@ -122,7 +115,6 @@ error: parameter of type `HashMap` should be generalized over different hashers
...
84 | gen!(fn bar);
| ------------- in this macro invocation
|
help: consider adding a type parameter
|
78 | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {
@ -136,7 +128,6 @@ error: parameter of type `HashSet` should be generalized over different hashers
...
84 | gen!(fn bar);
| ------------- in this macro invocation
|
help: consider adding a type parameter
|
78 | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {

View File

@ -15,7 +15,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=`
|
11 | y + 1 <= x;
| ^^^^^^^^^^
|
help: change `>= y + 1` to `> y` as shown
|
11 | y < x;
@ -26,7 +25,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=`
|
13 | x - 1 >= y;
| ^^^^^^^^^^
|
help: change `>= y + 1` to `> y` as shown
|
13 | x > y;
@ -37,7 +35,6 @@ error: Unnecessary `>= y + 1` or `x - 1 >=`
|
14 | y <= x - 1;
| ^^^^^^^^^^
|
help: change `>= y + 1` to `> y` as shown
|
14 | y < x;

View File

@ -27,7 +27,6 @@ error: large size difference between variants
|
34 | ContainingLargeEnum(LargeEnum),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider boxing the large fields to reduce the total size of the enum
|
34 | ContainingLargeEnum(Box<LargeEnum>),
@ -62,7 +61,6 @@ error: large size difference between variants
|
49 | StructLikeLarge2 { x: [i32; 8000] },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider boxing the large fields to reduce the total size of the enum
|
49 | StructLikeLarge2 { x: Box<[i32; 8000]> },

View File

@ -77,7 +77,6 @@ error: this is a decimal constant
|
30 | let fail8 = 0123;
| ^^^^
|
help: if you mean to use a decimal constant, remove the `0` to remove confusion
|
30 | let fail8 = 123;

View File

@ -143,7 +143,6 @@ error: you don't need to add `&` to all patterns
150 | | _ => println!("none"),
151 | | }
| |_____^
|
help: instead of prefixing all patterns with `&`, you can dereference the expression
|
148 | match *tup { .. }
@ -165,7 +164,6 @@ error: you don't need to add `&` to all patterns
166 | | println!("none");
167 | | }
| |_____^
|
help: instead of prefixing all patterns with `&`, you can dereference the expression
|
165 | if let .. = *a { .. }

View File

@ -212,7 +212,6 @@ error: called `map_or(None, f)` on an Option value. This can be done more direct
151 | | }
152 | | );
| |_________________^
|
help: try using and_then instead
|
149 | let _ = opt.and_then(|x| {

View File

@ -29,7 +29,6 @@ error: this argument is passed by value, but not consumed in the function body
|
44 | fn test_match(x: Option<Option<String>>, y: Option<Option<String>>) {
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: consider taking a reference instead
|
44 | fn test_match(x: &Option<Option<String>>, y: Option<Option<String>>) {
@ -47,7 +46,6 @@ error: this argument is passed by value, but not consumed in the function body
|
57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
| ^^^^^^^
|
help: consider taking a reference instead
|
57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) {
@ -73,7 +71,6 @@ error: this argument is passed by value, but not consumed in the function body
|
75 | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^
|
help: consider changing the type to
|
75 | fn issue_2114(s: String, t: &str, u: Vec<i32>, v: Vec<i32>) {
@ -94,7 +91,6 @@ error: this argument is passed by value, but not consumed in the function body
|
75 | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^^^
|
help: consider changing the type to
|
75 | fn issue_2114(s: String, t: String, u: Vec<i32>, v: &[i32]) {

View File

@ -19,7 +19,6 @@ error: the loop variable `i` is only used to index `ms`.
30 | | ms[i] *= 2;
31 | | }
| |_____^
|
help: consider using an iterator
|
29 | for <item> in &mut ms {
@ -33,7 +32,6 @@ error: the loop variable `i` is only used to index `ms`.
37 | | *x *= 2;
38 | | }
| |_____^
|
help: consider using an iterator
|
35 | for <item> in &mut ms {

View File

@ -15,7 +15,6 @@ error: you should consider deriving a `Default` implementation for `Bar`
|
16 | pub fn new() -> Self { Bar }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: try this
|
13 | #[derive(Default)]

View File

@ -23,7 +23,6 @@ error: writing `&Vec<_>` instead of `&[_]` involves one more reference and canno
|
40 | fn cloned(x: &Vec<u8>) -> Vec<u8> {
| ^^^^^^^^
|
help: change this to
|
40 | fn cloned(x: &[u8]) -> Vec<u8> {
@ -42,7 +41,6 @@ error: writing `&String` instead of `&str` involves a new object where a slice w
|
49 | fn str_cloned(x: &String) -> String {
| ^^^^^^^
|
help: change this to
|
49 | fn str_cloned(x: &str) -> String {
@ -65,7 +63,6 @@ error: writing `&String` instead of `&str` involves a new object where a slice w
|
59 | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
| ^^^^^^^
|
help: change this to
|
59 | fn false_positive_capacity(x: &Vec<u8>, y: &str) {