Skip to content

Commit 879ecce

Browse files
committed
Auto merge of rust-lang#91957 - nnethercote:rm-SymbolStr, r=oli-obk
Remove `SymbolStr` This was originally proposed in rust-lang#74554 (comment). As well as removing the icky `SymbolStr` type, it allows the removal of a lot of `&` and `*` occurrences. Best reviewed one commit at a time. r? `@oli-obk`
2 parents af1eea3 + a83c935 commit 879ecce

40 files changed

+77
-75
lines changed

clippy_lints/src/attrs.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_semver::RustcVersion;
1717
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
1818
use rustc_span::source_map::Span;
1919
use rustc_span::sym;
20-
use rustc_span::symbol::{Symbol, SymbolStr};
20+
use rustc_span::symbol::Symbol;
2121
use semver::Version;
2222

2323
static UNIX_SYSTEMS: &[&str] = &[
@@ -310,8 +310,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
310310
|| is_word(lint, sym::deprecated)
311311
|| is_word(lint, sym!(unreachable_pub))
312312
|| is_word(lint, sym!(unused))
313-
|| extract_clippy_lint(lint).map_or(false, |s| s == "wildcard_imports")
314-
|| extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use")
313+
|| extract_clippy_lint(lint).map_or(false, |s| s.as_str() == "wildcard_imports")
314+
|| extract_clippy_lint(lint).map_or(false, |s| s.as_str() == "enum_glob_use")
315315
{
316316
return;
317317
}
@@ -370,15 +370,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
370370
}
371371

372372
/// Returns the lint name if it is clippy lint.
373-
fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> {
373+
fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> {
374374
if_chain! {
375375
if let Some(meta_item) = lint.meta_item();
376376
if meta_item.path.segments.len() > 1;
377377
if let tool_name = meta_item.path.segments[0].ident;
378378
if tool_name.name == sym::clippy;
379379
then {
380380
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
381-
return Some(lint_name.as_str());
381+
return Some(lint_name);
382382
}
383383
}
384384
None
@@ -387,7 +387,7 @@ fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> {
387387
fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
388388
for lint in items {
389389
if let Some(lint_name) = extract_clippy_lint(lint) {
390-
if lint_name == "restriction" && name != sym::allow {
390+
if lint_name.as_str() == "restriction" && name != sym::allow {
391391
span_lint_and_help(
392392
cx,
393393
BLANKET_CLIPPY_RESTRICTION_LINTS,
@@ -486,7 +486,7 @@ fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribut
486486

487487
fn check_semver(cx: &LateContext<'_>, span: Span, lit: &Lit) {
488488
if let LitKind::Str(is, _) = lit.kind {
489-
if Version::parse(&is.as_str()).is_ok() {
489+
if Version::parse(is.as_str()).is_ok() {
490490
return;
491491
}
492492
}
@@ -619,7 +619,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
619619
MetaItemKind::Word => {
620620
if_chain! {
621621
if let Some(ident) = meta.ident();
622-
if let Some(os) = find_os(&*ident.name.as_str());
622+
if let Some(os) = find_os(ident.name.as_str());
623623
then {
624624
mismatched.push((os, ident.span));
625625
}

clippy_lints/src/booleans.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
272272
.copied()
273273
.flat_map(|(a, b)| vec![(a, b), (b, a)])
274274
.find(|&(a, _)| {
275-
let path: &str = &path.ident.name.as_str();
275+
let path: &str = path.ident.name.as_str();
276276
a == path
277277
})
278278
.and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method)))

clippy_lints/src/checked_conversions.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
321321
if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind;
322322
if let [int] = &*tp.segments;
323323
then {
324-
let name = &int.ident.name.as_str();
325-
candidates.iter().find(|c| name == *c).copied()
324+
let name = int.ident.name.as_str();
325+
candidates.iter().find(|c| &name == *c).copied()
326326
} else {
327327
None
328328
}
@@ -335,8 +335,8 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
335335
if let QPath::Resolved(_, path) = *path;
336336
if let [ty] = &*path.segments;
337337
then {
338-
let name = &ty.ident.name.as_str();
339-
INTS.iter().find(|c| name == *c).copied()
338+
let name = ty.ident.name.as_str();
339+
INTS.iter().find(|c| &name == *c).copied()
340340
} else {
341341
None
342342
}

clippy_lints/src/doc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
437437

438438
for attr in attrs {
439439
if let AttrKind::DocComment(comment_kind, comment) = attr.kind {
440-
let (comment, current_spans) = strip_doc_comment_decoration(&comment.as_str(), comment_kind, attr.span);
440+
let (comment, current_spans) = strip_doc_comment_decoration(comment.as_str(), comment_kind, attr.span);
441441
spans.extend_from_slice(&current_spans);
442442
doc.push_str(&comment);
443443
} else if attr.has_name(sym::doc) {

clippy_lints/src/duration_subsec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for DurationSubsec {
4949
if match_type(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), &paths::DURATION);
5050
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right);
5151
then {
52-
let suggested_fn = match (method_path.ident.as_str().as_ref(), divisor) {
52+
let suggested_fn = match (method_path.ident.as_str(), divisor) {
5353
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
5454
("subsec_nanos", 1_000) => "subsec_micros",
5555
_ => return,

clippy_lints/src/enum_variants.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ fn check_variant(
153153
);
154154
}
155155
}
156-
let first = &def.variants[0].ident.name.as_str();
156+
let first = def.variants[0].ident.name.as_str();
157157
let mut pre = &first[..str_utils::camel_case_until(&*first).byte_index];
158158
let mut post = &first[str_utils::camel_case_start(&*first).byte_index..];
159159
for var in def.variants {

clippy_lints/src/float_literal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
6868
if let LitKind::Float(sym, lit_float_ty) = lit.node;
6969
then {
7070
let sym_str = sym.as_str();
71-
let formatter = FloatFormat::new(&sym_str);
71+
let formatter = FloatFormat::new(sym_str);
7272
// Try to bail out if the float is for sure fine.
7373
// If its within the 2 decimal digits of being out of precision we
7474
// check if the parsed representation is the same as the string

clippy_lints/src/floating_point_arithmetic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>
595595
return method_name_a.as_str() == method_name_b.as_str() &&
596596
args_a.len() == args_b.len() &&
597597
(
598-
["ln", "log2", "log10"].contains(&&*method_name_a.as_str()) ||
598+
["ln", "log2", "log10"].contains(&method_name_a.as_str()) ||
599599
method_name_a.as_str() == "log" && args_a.len() == 2 && eq_expr_value(cx, &args_a[1], &args_b[1])
600600
);
601601
}
@@ -692,7 +692,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
692692
let recv_ty = cx.typeck_results().expr_ty(&args[0]);
693693

694694
if recv_ty.is_floating_point() {
695-
match &*path.ident.name.as_str() {
695+
match path.ident.name.as_str() {
696696
"ln" => check_ln1p(cx, expr, args),
697697
"log" => check_log_base(cx, expr, args),
698698
"powf" => check_powf(cx, expr, args),

clippy_lints/src/iter_not_returning_iterator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ declare_lint_pass!(IterNotReturningIterator => [ITER_NOT_RETURNING_ITERATOR]);
4242

4343
impl LateLintPass<'_> for IterNotReturningIterator {
4444
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'tcx>) {
45-
let name: &str = &impl_item.ident.name.as_str();
45+
let name = impl_item.ident.name.as_str();
4646
if_chain! {
4747
if let ImplItemKind::Fn(fn_sig, _) = &impl_item.kind;
4848
let ret_ty = return_ty(cx, impl_item.hir_id());

clippy_lints/src/loops/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
659659
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
660660

661661
if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind {
662-
let method_name = &*method.ident.as_str();
662+
let method_name = method.ident.as_str();
663663
// check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
664664
match method_name {
665665
"iter" | "iter_mut" => explicit_iter_loop::check(cx, self_arg, arg, method_name),

clippy_lints/src/loops/needless_collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
3131
let ty = cx.typeck_results().expr_ty(&args[0]);
3232
let mut applicability = Applicability::MaybeIncorrect;
3333
let is_empty_sugg = "next().is_none()".to_string();
34-
let method_name = &*method.ident.name.as_str();
34+
let method_name = method.ident.name.as_str();
3535
let sugg = if is_type_diagnostic_item(cx, ty, sym::Vec) ||
3636
is_type_diagnostic_item(cx, ty, sym::VecDeque) ||
3737
is_type_diagnostic_item(cx, ty, sym::LinkedList) ||
@@ -210,7 +210,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
210210
if let Some(hir_id) = self.current_statement_hir_id {
211211
self.hir_id_uses_map.insert(hir_id, self.uses.len());
212212
}
213-
match &*method_name.ident.name.as_str() {
213+
match method_name.ident.name.as_str() {
214214
"into_iter" => self.uses.push(Some(IterFunction {
215215
func: IterFunctionKind::IntoIter,
216216
span: expr.span,

clippy_lints/src/match_str_case_mismatch.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::hir::map::Map;
99
use rustc_middle::lint::in_external_macro;
1010
use rustc_middle::ty;
1111
use rustc_session::{declare_lint_pass, declare_tool_lint};
12-
use rustc_span::symbol::SymbolStr;
12+
use rustc_span::symbol::Symbol;
1313
use rustc_span::{sym, Span};
1414

1515
declare_clippy_lint! {
@@ -71,8 +71,8 @@ impl LateLintPass<'_> for MatchStrCaseMismatch {
7171
visitor.visit_expr(match_expr);
7272

7373
if let Some(case_method) = visitor.case_method {
74-
if let Some((bad_case_span, bad_case_str)) = verify_case(&case_method, arms) {
75-
lint(cx, &case_method, bad_case_span, &bad_case_str);
74+
if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) {
75+
lint(cx, &case_method, bad_case_span, bad_case_sym.as_str());
7676
}
7777
}
7878
}
@@ -95,7 +95,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
9595
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
9696
match ex.kind {
9797
ExprKind::MethodCall(segment, _, [receiver], _)
98-
if self.case_altered(&*segment.ident.as_str(), receiver) => {},
98+
if self.case_altered(segment.ident.as_str(), receiver) => {},
9999
_ => walk_expr(self, ex),
100100
}
101101
}
@@ -126,7 +126,7 @@ fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> {
126126
}
127127
}
128128

129-
fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> {
129+
fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, Symbol)> {
130130
let case_check = match case_method {
131131
CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) },
132132
CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) },
@@ -144,7 +144,7 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
144144
let input = symbol.as_str();
145145
if !case_check(&input);
146146
then {
147-
return Some((lit.span, input));
147+
return Some((lit.span, symbol));
148148
}
149149
}
150150
}

clippy_lints/src/matches.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
966966
for pat in inner.iter() {
967967
if let PatKind::Binding(_, id, ident, None) = pat.kind {
968968
if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
969-
ident_bind_name = (&ident.name.as_str()).to_string();
969+
ident_bind_name = ident.name.as_str().to_string();
970970
matching_wild = true;
971971
}
972972
}
@@ -1127,7 +1127,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
11271127
if let CommonPrefixSearcher::Path(path_prefix) = path_prefix {
11281128
let mut s = String::new();
11291129
for seg in path_prefix {
1130-
s.push_str(&seg.ident.as_str());
1130+
s.push_str(seg.ident.as_str());
11311131
s.push_str("::");
11321132
}
11331133
s

clippy_lints/src/methods/manual_saturating_arithmetic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<M
8181
if args.is_empty();
8282
if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind;
8383
then {
84-
match &*segment.ident.as_str() {
84+
match segment.ident.as_str() {
8585
"max_value" => return Some(MinMax::Max),
8686
"min_value" => return Some(MinMax::Min),
8787
_ => {}

clippy_lints/src/methods/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ use rustc_middle::lint::in_external_macro;
8080
use rustc_middle::ty::{self, TraitRef, Ty, TyS};
8181
use rustc_semver::RustcVersion;
8282
use rustc_session::{declare_tool_lint, impl_lint_pass};
83-
use rustc_span::symbol::SymbolStr;
83+
use rustc_span::symbol::Symbol;
8484
use rustc_span::{sym, Span};
8585
use rustc_typeck::hir_ty_to_ty;
8686

@@ -1997,21 +1997,21 @@ impl_lint_pass!(Methods => [
19971997
]);
19981998

19991999
/// Extracts a method call name, args, and `Span` of the method name.
2000-
fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(SymbolStr, &'tcx [hir::Expr<'tcx>], Span)> {
2000+
fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(Symbol, &'tcx [hir::Expr<'tcx>], Span)> {
20012001
if let ExprKind::MethodCall(path, span, args, _) = recv.kind {
20022002
if !args.iter().any(|e| e.span.from_expansion()) {
2003-
return Some((path.ident.name.as_str(), args, span));
2003+
return Some((path.ident.name, args, span));
20042004
}
20052005
}
20062006
None
20072007
}
20082008

2009-
/// Same as `method_call` but the `SymbolStr` is dereferenced into a temporary `&str`
2009+
/// Same as `method_call` but the `Symbol` is dereferenced into a temporary `&str`
20102010
macro_rules! method_call {
20112011
($expr:expr) => {
20122012
method_call($expr)
20132013
.as_ref()
2014-
.map(|&(ref name, args, span)| (&**name, args, span))
2014+
.map(|&(ref name, args, span)| (name.as_str(), args, span))
20152015
};
20162016
}
20172017

@@ -2028,8 +2028,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
20282028
from_iter_instead_of_collect::check(cx, expr, args, func);
20292029
},
20302030
hir::ExprKind::MethodCall(method_call, ref method_span, args, _) => {
2031-
or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
2032-
expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
2031+
or_fun_call::check(cx, expr, *method_span, method_call.ident.as_str(), args);
2032+
expect_fun_call::check(cx, expr, *method_span, method_call.ident.as_str(), args);
20332033
clone_on_copy::check(cx, expr, method_call.ident.name, args);
20342034
clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
20352035
inefficient_to_string::check(cx, expr, method_call.ident.name, args);
@@ -2184,7 +2184,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
21842184
let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
21852185
wrong_self_convention::check(
21862186
cx,
2187-
&item.ident.name.as_str(),
2187+
item.ident.name.as_str(),
21882188
self_ty,
21892189
first_arg_ty,
21902190
first_arg_span,

clippy_lints/src/methods/str_splitn.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ fn parse_iter_usage(
140140
let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
141141
let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?;
142142

143-
match (&*name.ident.as_str(), args) {
143+
match (name.ident.as_str(), args) {
144144
("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
145145
if reverse {
146146
(IterUsageKind::Second, e.span)
@@ -298,7 +298,7 @@ fn check_iter(
298298
if let Some(did) = cx.typeck_results().type_dependent_def_id(e.hir_id);
299299
if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
300300
then {
301-
match (&*name.ident.as_str(), args) {
301+
match (name.ident.as_str(), args) {
302302
("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
303303
return true;
304304
},

clippy_lints/src/misc.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
407407
// Don't lint things expanded by #[derive(...)], etc or `await` desugaring
408408
return;
409409
}
410+
let sym;
410411
let binding = match expr.kind {
411412
ExprKind::Path(ref qpath) if !matches!(qpath, hir::QPath::LangItem(..)) => {
412413
let binding = last_path_segment(qpath).ident.as_str();
@@ -423,7 +424,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
423424
}
424425
},
425426
ExprKind::Field(_, ident) => {
426-
let name = ident.as_str();
427+
sym = ident.name;
428+
let name = sym.as_str();
427429
if name.starts_with('_') && !name.starts_with("__") {
428430
Some(name)
429431
} else {

clippy_lints/src/missing_enforced_import_rename.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl LateLintPass<'_> for ImportRename {
7575
if let Some(import) = match snip.split_once(" as ") {
7676
None => Some(snip.as_str()),
7777
Some((import, rename)) => {
78-
if rename.trim() == &*name.as_str() {
78+
if rename.trim() == name.as_str() {
7979
None
8080
} else {
8181
Some(import.trim())

clippy_lints/src/multiple_crate_versions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ impl LateLintPass<'_> for MultipleCrateVersions {
4848
}
4949

5050
let metadata = unwrap_cargo_metadata!(cx, MULTIPLE_CRATE_VERSIONS, true);
51-
let local_name = cx.tcx.crate_name(LOCAL_CRATE).as_str();
51+
let local_name = cx.tcx.crate_name(LOCAL_CRATE);
5252
let mut packages = metadata.packages;
5353
packages.sort_by(|a, b| a.name.cmp(&b.name));
5454

5555
if_chain! {
5656
if let Some(resolve) = &metadata.resolve;
5757
if let Some(local_id) = packages
5858
.iter()
59-
.find_map(|p| if p.name == *local_name { Some(&p.id) } else { None });
59+
.find_map(|p| if p.name == local_name.as_str() { Some(&p.id) } else { None });
6060
then {
6161
for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
6262
let group: Vec<&Package> = group.collect();

clippy_lints/src/mut_reference.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
4949
let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
5050
let substs = cx.typeck_results().node_substs(e.hir_id);
5151
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
52-
check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method");
52+
check_arguments(cx, arguments, method_type, path.ident.as_str(), "method");
5353
},
5454
_ => (),
5555
}

0 commit comments

Comments
 (0)