mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-04 04:39:16 +00:00
Test for coercion between (FnDef | Closure) and (FnDef | Closure)
This commit is contained in:
parent
59cc5b1ba3
commit
42396b1fac
39
src/test/ui/closures/closure_cap_coerce_many_fail.rs
Normal file
39
src/test/ui/closures/closure_cap_coerce_many_fail.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
// We shouldn't coerce capturing closure to a function
|
||||||
|
let cap = 0;
|
||||||
|
let _ = match "+" {
|
||||||
|
"+" => add,
|
||||||
|
"-" => |a, b| (a - b + cap) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
//~^^^ ERROR `match` arms have incompatible types
|
||||||
|
|
||||||
|
|
||||||
|
// We shouldn't coerce capturing closure to a non-capturing closure
|
||||||
|
let _ = match "+" {
|
||||||
|
"+" => |a, b| (a + b) as i32,
|
||||||
|
"-" => |a, b| (a - b + cap) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
//~^^^ ERROR `match` arms have incompatible types
|
||||||
|
|
||||||
|
|
||||||
|
// We shouldn't coerce non-capturing closure to a capturing closure
|
||||||
|
let _ = match "+" {
|
||||||
|
"+" => |a, b| (a + b + cap) as i32,
|
||||||
|
"-" => |a, b| (a - b) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
//~^^^ ERROR `match` arms have incompatible types
|
||||||
|
|
||||||
|
// We shouldn't coerce capturing closure to a capturing closure
|
||||||
|
let _ = match "+" {
|
||||||
|
"+" => |a, b| (a + b + cap) as i32,
|
||||||
|
"-" => |a, b| (a - b + cap) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
//~^^^ ERROR `match` arms have incompatible types
|
||||||
|
}
|
73
src/test/ui/closures/closure_cap_coerce_many_fail.stderr
Normal file
73
src/test/ui/closures/closure_cap_coerce_many_fail.stderr
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/closure_cap_coerce_many_fail.rs:9:16
|
||||||
|
|
|
||||||
|
LL | let _ = match "+" {
|
||||||
|
| _____________-
|
||||||
|
LL | | "+" => add,
|
||||||
|
| | --- this is found to be of type `fn(i32, i32) -> i32 {add}`
|
||||||
|
LL | | "-" => |a, b| (a - b + cap) as i32,
|
||||||
|
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found closure
|
||||||
|
LL | | _ => unimplemented!(),
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `fn(i32, i32) -> i32 {add}`
|
||||||
|
found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:43 cap:_]`
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/closure_cap_coerce_many_fail.rs:18:16
|
||||||
|
|
|
||||||
|
LL | let _ = match "+" {
|
||||||
|
| _____________-
|
||||||
|
LL | | "+" => |a, b| (a + b) as i32,
|
||||||
|
| | --------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]`
|
||||||
|
LL | | "-" => |a, b| (a - b + cap) as i32,
|
||||||
|
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
||||||
|
LL | | _ => unimplemented!(),
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]`
|
||||||
|
found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:43 cap:_]`
|
||||||
|
= note: no two closures, even if identical, have the same type
|
||||||
|
= help: consider boxing your closure and/or using it as a trait object
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/closure_cap_coerce_many_fail.rs:27:16
|
||||||
|
|
|
||||||
|
LL | let _ = match "+" {
|
||||||
|
| _____________-
|
||||||
|
LL | | "+" => |a, b| (a + b + cap) as i32,
|
||||||
|
| | --------------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43 cap:_]`
|
||||||
|
LL | | "-" => |a, b| (a - b) as i32,
|
||||||
|
| | ^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
||||||
|
LL | | _ => unimplemented!(),
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43 cap:_]`
|
||||||
|
found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:37]`
|
||||||
|
= note: no two closures, even if identical, have the same type
|
||||||
|
= help: consider boxing your closure and/or using it as a trait object
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/closure_cap_coerce_many_fail.rs:35:16
|
||||||
|
|
|
||||||
|
LL | let _ = match "+" {
|
||||||
|
| _____________-
|
||||||
|
LL | | "+" => |a, b| (a + b + cap) as i32,
|
||||||
|
| | --------------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43 cap:_]`
|
||||||
|
LL | | "-" => |a, b| (a - b + cap) as i32,
|
||||||
|
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
||||||
|
LL | | _ => unimplemented!(),
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43 cap:_]`
|
||||||
|
found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:43 cap:_]`
|
||||||
|
= note: no two closures, even if identical, have the same type
|
||||||
|
= help: consider boxing your closure and/or using it as a trait object
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
166
src/test/ui/closures/closure_no_cap_coerce_many_check_pass.rs
Normal file
166
src/test/ui/closures/closure_no_cap_coerce_many_check_pass.rs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// check-pass
|
||||||
|
// Ensure non-capturing Closure passes CoerceMany.
|
||||||
|
fn foo(x: usize) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar(x: usize) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// One FnDef and one non-capturing Closure
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
2 => |a| 2,
|
||||||
|
0 => foo,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = [foo, |a| 2];
|
||||||
|
let _ = [|a| 2, foo];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Two FnDefs and one non-capturing Closure
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo,
|
||||||
|
1 => bar,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo,
|
||||||
|
2 => |a| 2,
|
||||||
|
1 => bar,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
2 => |a| 2,
|
||||||
|
0 => foo,
|
||||||
|
1 => bar,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = [foo, bar, |a| 2];
|
||||||
|
let _ = [foo, |a| 2, bar];
|
||||||
|
let _ = [|a| 2, foo, bar];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// One FnDef and two non-capturing Closures
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo,
|
||||||
|
1 => |a| 1,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
1 => |a| 1,
|
||||||
|
0 => foo,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
1 => |a| 1,
|
||||||
|
2 => |a| 2,
|
||||||
|
0 => foo,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = [foo, |a| 1, |a| 2];
|
||||||
|
let _ = [|a| 1, foo, |a| 2];
|
||||||
|
let _ = [|a| 1, |a| 2, foo];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Three non-capturing Closures
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => |a: usize| 0,
|
||||||
|
1 => |a| 1,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = [|a: usize| 0, |a| 1, |a| 2];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Three non-capturing Closures variable
|
||||||
|
let clo0 = |a: usize| 0;
|
||||||
|
let clo1 = |a| 1;
|
||||||
|
let clo2 = |a| 2;
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => clo0,
|
||||||
|
1 => clo1,
|
||||||
|
2 => clo2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let clo0 = |a: usize| 0;
|
||||||
|
let clo1 = |a| 1;
|
||||||
|
let clo2 = |a| 2;
|
||||||
|
let _ = [clo0, clo1, clo2];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Function pointer related part
|
||||||
|
|
||||||
|
// Closure is not in a variable
|
||||||
|
type FnPointer = fn(usize) -> usize;
|
||||||
|
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo as FnPointer,
|
||||||
|
2 => |a| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let _ = match 0 {
|
||||||
|
2 => |a| 2,
|
||||||
|
0 => foo as FnPointer,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let _ = [foo as FnPointer, |a| 2];
|
||||||
|
let _ = [|a| 2, foo as FnPointer];
|
||||||
|
let _ = [foo, bar, |x| x];
|
||||||
|
let _ = [foo as FnPointer, bar, |x| x];
|
||||||
|
let _ = [foo, bar as FnPointer, |x| x];
|
||||||
|
let _ = [foo, bar, (|x| x) as FnPointer];
|
||||||
|
let _ = [foo as FnPointer, bar as FnPointer, |x| x];
|
||||||
|
|
||||||
|
// Closure is in a variable
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = match 0 {
|
||||||
|
0 => foo as FnPointer,
|
||||||
|
2 => x,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = match 0 {
|
||||||
|
2 => x,
|
||||||
|
0 => foo as FnPointer,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = [foo as FnPointer, x];
|
||||||
|
let _ = [x, foo as FnPointer];
|
||||||
|
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = [foo, bar, x];
|
||||||
|
let x: FnPointer = |a| 2;
|
||||||
|
let _ = [foo, bar, x];
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = [foo, bar as FnPointer, x];
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = [foo as FnPointer, bar, x];
|
||||||
|
let x = |a| 2;
|
||||||
|
let _ = [foo as FnPointer, bar as FnPointer, x];
|
||||||
|
}
|
59
src/test/ui/closures/closure_no_cap_coerce_many_run_pass.rs
Normal file
59
src/test/ui/closures/closure_no_cap_coerce_many_run_pass.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// run-pass
|
||||||
|
// Ensure non-capturing Closure passing CoerceMany work correctly.
|
||||||
|
fn foo(_: usize) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar(_: usize) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Coerce result check
|
||||||
|
|
||||||
|
type FnPointer = fn(usize) -> usize;
|
||||||
|
|
||||||
|
let c = |x| x;
|
||||||
|
let c_pointer: FnPointer = c;
|
||||||
|
assert_eq!(c_pointer(42), 42);
|
||||||
|
|
||||||
|
let f = match 0 {
|
||||||
|
0 => foo,
|
||||||
|
1 => |_| 1,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(f(42), 0);
|
||||||
|
|
||||||
|
let f = match 2 {
|
||||||
|
2 => |_| 2,
|
||||||
|
0 => foo,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(f(42), 2);
|
||||||
|
|
||||||
|
let f = match 1 {
|
||||||
|
0 => foo,
|
||||||
|
1 => bar,
|
||||||
|
2 => |_| 2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(f(42), 1);
|
||||||
|
|
||||||
|
let clo0 = |_: usize| 0;
|
||||||
|
let clo1 = |_| 1;
|
||||||
|
let clo2 = |_| 2;
|
||||||
|
let f = match 0 {
|
||||||
|
0 => clo0,
|
||||||
|
1 => clo1,
|
||||||
|
2 => clo2,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(f(42), 0);
|
||||||
|
|
||||||
|
let funcs = [add, |a, b| (a - b) as i32];
|
||||||
|
assert_eq!([funcs[0](5, 5), funcs[1](5, 5)], [10, 0]);
|
||||||
|
}
|
22
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs
Normal file
22
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Ensure we get unsafe function after coercion
|
||||||
|
unsafe fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
// We can coerce non-capturing closure to unsafe function
|
||||||
|
let foo = match "+" {
|
||||||
|
"+" => add,
|
||||||
|
"-" => |a, b| (a - b) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let result: i32 = foo(5, 5); //~ ERROR call to unsafe function
|
||||||
|
|
||||||
|
|
||||||
|
// We can coerce unsafe function to non-capturing closure
|
||||||
|
let foo = match "+" {
|
||||||
|
"-" => |a, b| (a - b) as i32,
|
||||||
|
"+" => add,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
let result: i32 = foo(5, 5); //~ ERROR call to unsafe function
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:12:23
|
||||||
|
|
|
||||||
|
LL | let result: i32 = foo(5, 5);
|
||||||
|
| ^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:21:23
|
||||||
|
|
|
||||||
|
LL | let result: i32 = foo(5, 5);
|
||||||
|
| ^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
23
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs
Normal file
23
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// run-pass
|
||||||
|
// Ensure we get correct unsafe function after coercion
|
||||||
|
unsafe fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
// We can coerce non-capturing closure to unsafe function
|
||||||
|
let foo = match "+" {
|
||||||
|
"+" => add,
|
||||||
|
"-" => |a, b| (a - b) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(unsafe { foo(5, 5) }, 10);
|
||||||
|
|
||||||
|
|
||||||
|
// We can coerce unsafe function to non-capturing closure
|
||||||
|
let foo = match "-" {
|
||||||
|
"-" => |a, b| (a - b) as i32,
|
||||||
|
"+" => add,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
assert_eq!(unsafe { foo(5, 5) }, 0);
|
||||||
|
}
|
9
src/test/ui/closures/issue-46742.rs
Normal file
9
src/test/ui/closures/issue-46742.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// check-pass
|
||||||
|
fn main() {
|
||||||
|
let _: i32 = (match "" {
|
||||||
|
"+" => ::std::ops::Add::add,
|
||||||
|
"-" => ::std::ops::Sub::sub,
|
||||||
|
"<" => |a,b| (a < b) as i32,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
})(5, 5);
|
||||||
|
}
|
14
src/test/ui/closures/issue-48109.rs
Normal file
14
src/test/ui/closures/issue-48109.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// check-pass
|
||||||
|
fn useful(i: usize) -> usize {
|
||||||
|
i
|
||||||
|
}
|
||||||
|
|
||||||
|
fn useful2(i: usize) -> usize {
|
||||||
|
i
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for f in &[useful, useful2, |x| x] {
|
||||||
|
println!("{}", f(6));
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ fn closure_from_match() {
|
|||||||
2 => |c| c - 1,
|
2 => |c| c - 1,
|
||||||
_ => |c| c - 1
|
_ => |c| c - 1
|
||||||
};
|
};
|
||||||
//~^^^ ERROR `match` arms have incompatible types
|
//~^^^^ ERROR type annotations needed
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
@ -11,24 +11,13 @@ LL | x = |c| c + 1;
|
|||||||
= note: no two closures, even if identical, have the same type
|
= note: no two closures, even if identical, have the same type
|
||||||
= help: consider boxing your closure and/or using it as a trait object
|
= help: consider boxing your closure and/or using it as a trait object
|
||||||
|
|
||||||
error[E0308]: `match` arms have incompatible types
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/issue-24036.rs:10:14
|
--> $DIR/issue-24036.rs:9:15
|
||||||
|
|
|
|
||||||
LL | let x = match 1usize {
|
LL | 1 => |c| c + 1,
|
||||||
| _____________-
|
| ^ consider giving this closure parameter a type
|
||||||
LL | | 1 => |c| c + 1,
|
|
||||||
| | --------- this is found to be of type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
|
|
||||||
LL | | 2 => |c| c - 1,
|
|
||||||
| | ^^^^^^^^^ expected closure, found a different closure
|
|
||||||
LL | | _ => |c| c - 1
|
|
||||||
LL | | };
|
|
||||||
| |_____- `match` arms have incompatible types
|
|
||||||
|
|
|
||||||
= note: expected type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
|
|
||||||
found closure `[closure@$DIR/issue-24036.rs:10:14: 10:23]`
|
|
||||||
= note: no two closures, even if identical, have the same type
|
|
||||||
= help: consider boxing your closure and/or using it as a trait object
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
Some errors have detailed explanations: E0282, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0282`.
|
||||||
|
Loading…
Reference in New Issue
Block a user