diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 41ccd88b4a887..b9367458ea9f2 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -407,8 +407,8 @@ impl Term { /// Get a reference to the interned string. #[unstable(feature = "proc_macro", issue = "38356")] - pub fn as_str(&self) -> &str { - unsafe { &*(&*self.0.as_str() as *const str) } + pub fn with_str R, R>(self, f: F) -> R { + self.0.with_str(f) } } @@ -678,8 +678,11 @@ impl TokenTree { }, TokenNode::Term(symbol) => { let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() }; - let token = - if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) }; + let token = if symbol.0.with_str(|str| str.starts_with("'")) { + Lifetime(ident) + } else { + Ident(ident) + }; return TokenTree::Token(self.span.0, token).into(); } TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(), diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs index 8b5add1a0f0d7..32e313d271703 100644 --- a/src/libproc_macro/quote.rs +++ b/src/libproc_macro/quote.rs @@ -162,7 +162,7 @@ impl Quote for usize { impl Quote for Term { fn quote(self) -> TokenStream { - quote!(::Term::intern((quote self.as_str()))) + self.with_str(|str| quote!(::Term::intern((quote str)))) } } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 003255f87966f..809bd67107ecf 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -49,11 +49,11 @@ impl<'a> CheckAttrVisitor<'a> { /// Check any attribute. fn check_attribute(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) { if let Some(name) = attr.name() { - match &*name.as_str() { + name.with_str(|str| match str { "inline" => self.check_inline(attr, item, target), "repr" => self.check_repr(attr, item, target), _ => (), - } + }) } } @@ -86,7 +86,7 @@ impl<'a> CheckAttrVisitor<'a> { None => continue, }; - let (message, label) = match &*name.as_str() { + let (message, label) = match &*name.to_string() { "C" => { is_c = true; if target != Target::Struct && diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9ab3b5ca15e70..33fd97d1fdb41 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1844,7 +1844,7 @@ pub struct StructField { impl StructField { // Still necessary in couple of places pub fn is_positional(&self) -> bool { - let first = self.name.as_str().as_bytes()[0]; + let first = self.name.with_str(|str| str.as_bytes()[0]); first >= b'0' && first <= b'9' } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 2f9fc70252f8d..7cfdeb16ea8d0 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -528,11 +528,13 @@ impl<'a> State<'a> { self.head(&visibility_qualified(&item.vis, "extern crate"))?; if let Some(p) = *optional_path { let val = p.as_str(); - if val.contains("-") { - self.print_string(&val, ast::StrStyle::Cooked)?; - } else { - self.print_name(p)?; - } + val.with(|str| { + if str.contains("-") { + self.print_string(str, ast::StrStyle::Cooked) + } else { + self.print_name(p) + } + })?; self.s.space()?; self.s.word("as")?; self.s.space()?; @@ -623,7 +625,7 @@ impl<'a> State<'a> { } hir::ItemGlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global asm"))?; - self.s.word(&ga.asm.as_str())?; + ga.asm.with_str(|str| self.s.word(str))?; self.end()? } hir::ItemTy(ref ty, ref generics) => { @@ -1469,20 +1471,21 @@ impl<'a> State<'a> { hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => { self.s.word("asm!")?; self.popen()?; - self.print_string(&a.asm.as_str(), a.asm_str_style)?; + a.asm.with_str(|str| self.print_string(str, a.asm_str_style))?; self.word_space(":")?; let mut out_idx = 0; self.commasep(Inconsistent, &a.outputs, |s, out| { - let constraint = out.constraint.as_str(); - let mut ch = constraint.chars(); - match ch.next() { - Some('=') if out.is_rw => { - s.print_string(&format!("+{}", ch.as_str()), - ast::StrStyle::Cooked)? + out.constraint.with_str(|constraint| { + let mut ch = constraint.chars(); + match ch.next() { + Some('=') if out.is_rw => { + s.print_string(&format!("+{}", ch.as_str()), + ast::StrStyle::Cooked) + } + _ => s.print_string(&constraint, ast::StrStyle::Cooked) } - _ => s.print_string(&constraint, ast::StrStyle::Cooked)?, - } + })?; s.popen()?; s.print_expr(&outputs[out_idx])?; s.pclose()?; @@ -1494,7 +1497,7 @@ impl<'a> State<'a> { let mut in_idx = 0; self.commasep(Inconsistent, &a.inputs, |s, co| { - s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; + co.with_str(|str| s.print_string(str, ast::StrStyle::Cooked))?; s.popen()?; s.print_expr(&inputs[in_idx])?; s.pclose()?; @@ -1505,7 +1508,7 @@ impl<'a> State<'a> { self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, |s, co| { - s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; + co.with_str(|str| s.print_string(str, ast::StrStyle::Cooked))?; Ok(()) })?; @@ -1578,7 +1581,7 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - self.s.word(&name.as_str())?; + name.with_str(|str| self.s.word(str))?; self.ann.post(self, NodeName(&name)) } @@ -1936,7 +1939,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; if let Some(name) = arg_names.get(i) { - s.s.word(&name.node.as_str())?; + name.node.with_str(|str| s.s.word(str))?; s.s.word(":")?; s.s.space()?; } else if let Some(body_id) = body_id { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 57120d61e7c7b..cc8c3a7112851 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -33,8 +33,7 @@ impl<'gcx> HashStable> for InternedString { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher) { - let s: &str = &**self; - s.hash_stable(hcx, hasher); + self.with(|str| str.hash_stable(hcx, hasher)); } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 4bc37747f2a76..05844a1e7bca6 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -197,7 +197,8 @@ impl<'a> LintLevelsBuilder<'a> { "malformed lint attribute"); }; for attr in attrs { - let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) { + let level = match attr.name() + .and_then(|name| name.with_str(|str| Level::from_str(str))) { None => continue, Some(lvl) => lvl, }; @@ -221,7 +222,7 @@ impl<'a> LintLevelsBuilder<'a> { } }; let name = word.name(); - match store.check_lint_name(&name.as_str()) { + match name.with_str(|str| store.check_lint_name(str)) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span); for id in ids { @@ -256,8 +257,8 @@ impl<'a> LintLevelsBuilder<'a> { src, Some(li.span.into()), &msg); - if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase(); + if name.with_str(|str| str.chars().any(|c| c.is_uppercase())) { + let name_lower = name.with_str(|str| str.to_lowercase()); if let CheckLintNameResult::NoLint = store.check_lint_name(&name_lower) { db.emit(); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index f4abc54ad2e4e..a9dc0a0a289c4 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -441,7 +441,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session, &format!("requested on the command line with `{} {}`", flag, hyphen_case_lint_name)); } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + let hyphen_case_flag_val = lint_flag_val.with_str(|str| str.replace("_", "-")); sess.diag_note_once( &mut err, DiagnosticMessageId::from(lint), diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 21eb772b1b376..0a46c82d12c18 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -533,7 +533,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { name: ast::Name, node_type: &str, participle: &str) { - if !name.as_str().starts_with("_") { + if !name.with_str(|str| str.starts_with("_")) { self.tcx .lint_node(lint::builtin::DEAD_CODE, id, diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index dca676130b9a7..7243f87d20992 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -105,7 +105,7 @@ struct LanguageItemCollector<'a, 'tcx: 'a> { impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { if let Some(value) = extract(&item.attrs) { - let item_index = self.item_refs.get(&*value.as_str()).cloned(); + let item_index = value.with_str(|str| self.item_refs.get(str).cloned()); if let Some(item_index) = item_index { let def_id = self.tcx.hir.local_def_id(item.id); diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs index 6c87f750376fa..cead721f4f7a9 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/recursion_limit.rs @@ -35,7 +35,7 @@ fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Cell, } if let Some(s) = attr.value_str() { - if let Some(n) = s.as_str().parse().ok() { + if let Some(n) = s.with_str(|str| str.parse()).ok() { limit.set(n); return; } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e80ea16f565ab..4cc9c1deedd77 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -164,26 +164,29 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { if let (&Some(attr::RustcDeprecation {since: dep_since, ..}), &attr::Stable {since: stab_since}) = (&stab.rustc_depr, &stab.level) { // Explicit version of iter::order::lt to handle parse errors properly - for (dep_v, stab_v) in - dep_since.as_str().split(".").zip(stab_since.as_str().split(".")) { - if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), stab_v.parse()) { - match dep_v.cmp(&stab_v) { - Ordering::Less => { - self.tcx.sess.span_err(item_sp, "An API can't be stabilized \ - after it is deprecated"); - break + dep_since.with_str(|dep_since| stab_since.with_str(|stab_since| { + for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) { + if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), + stab_v.parse()) { + match dep_v.cmp(&stab_v) { + Ordering::Less => { + self.tcx.sess.span_err(item_sp, + "An API can't be stabilized \ + after it is deprecated"); + break + } + Ordering::Equal => continue, + Ordering::Greater => break, } - Ordering::Equal => continue, - Ordering::Greater => break, + } else { + // Act like it isn't less because the question is now nonsensical, + // and this makes us not do anything else interesting. + self.tcx.sess.span_err(item_sp, "Invalid stability or deprecation \ + version found"); + break } - } else { - // Act like it isn't less because the question is now nonsensical, - // and this makes us not do anything else interesting. - self.tcx.sess.span_err(item_sp, "Invalid stability or deprecation \ - version found"); - break } - } + })) } let hir_id = self.tcx.hir.node_to_hir_id(id); @@ -620,8 +623,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { - emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span, - GateIssue::Library(Some(issue)), &msg); + feature.with_str(|str| { + emit_feature_err(&self.sess.parse_sess, + str, + span, + GateIssue::Library(Some(issue)), + &msg) + }); } } Some(_) => { @@ -742,7 +750,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { remaining_lib_features.remove(&Symbol::intern("proc_macro")); for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { - let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) + let version = stable_lang_feature.with_str(|str| find_lang_feature_accepted_version(str)) .expect("unexpectedly couldn't find version feature was stabilized"); tcx.lint_node(lint::builtin::STABLE_FEATURES, ast::CRATE_NODE_ID, diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 50fb584070262..67073de4c2490 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &hir::ForeignItem) { if let Some(lang_item) = lang_items::extract(&i.attrs) { - self.register(&lang_item.as_str(), i.span); + lang_item.with_str(|str| self.register(str, i.span)); } intravisit::walk_foreign_item(self, i) } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 68f8098709c43..100abbf4b69c4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1652,7 +1652,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CtorKind::Fictive => { let mut struct_fmt = fmt.debug_struct(""); for (field, place) in variant_def.fields.iter().zip(places) { - struct_fmt.field(&field.name.as_str(), place); + field.name.with_str(|str| struct_fmt.field(str, place)); } struct_fmt.finish() } @@ -1671,7 +1671,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { tcx.with_freevars(node_id, |freevars| { for (freevar, place) in freevars.iter().zip(places) { let var_name = tcx.hir.name(freevar.var_id()); - struct_fmt.field(&var_name.as_str(), place); + var_name.with_str(|str| struct_fmt.field(str, place)); } }); @@ -1689,7 +1689,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { tcx.with_freevars(node_id, |freevars| { for (freevar, place) in freevars.iter().zip(places) { let var_name = tcx.hir.name(freevar.var_id()); - struct_fmt.field(&var_name.as_str(), place); + var_name.with_str(|str| struct_fmt.field(str, place)); } struct_fmt.field("$state", &places[freevars.len()]); for i in (freevars.len() + 1)..places.len() { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 54da23821f5d8..46286e9600ae3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -357,14 +357,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { - method = self.tcx.item_name(item); + method = self.tcx.item_name(item).to_string(); flags.push(("from_method", None)); flags.push(("from_method", Some(&*method))); } } if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { - desugaring = k.as_symbol().as_str(); + desugaring = k.as_symbol().to_string(); flags.push(("from_desugaring", None)); flags.push(("from_desugaring", Some(&*desugaring))); } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 16e200d56f9fb..9ac37161ec89a 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -182,11 +182,14 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| { - options.contains(&(&c.name().as_str(), - match c.value_str().map(|s| s.as_str()) { - Some(ref s) => Some(s), - None => None - })) + c.name().with_str(|str| { + match c.value_str().map(|s| s.as_str()) { + Some(ref s) => s.with(|value| { + options.contains(&(str, Some(value))) + }), + None => options.contains(&(str, None)), + } + }) }) { debug!("evaluate: skipping {:?} due to condition", command); continue @@ -229,42 +232,44 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); - let parser = Parser::new(&self.0); - let types = &generics.types; - let mut result = Ok(()); - for token in parser { - match token { - Piece::String(_) => (), // Normal string, no need to check it - Piece::NextArgument(a) => match a.position { - // `{Self}` is allowed - Position::ArgumentNamed(s) if s == "Self" => (), - // `{ThisTraitsName}` is allowed - Position::ArgumentNamed(s) if s == name => (), - // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match types.iter().find(|t| { - t.name == s - }) { - Some(_) => (), - None => { - span_err!(tcx.sess, span, E0230, - "there is no type parameter \ - {} on trait {}", - s, name); + self.0.with(|str| { + let parser = Parser::new(str); + let types = &generics.types; + let mut result = Ok(()); + for token in parser { + match token { + Piece::String(_) => (), // Normal string, no need to check it + Piece::NextArgument(a) => match a.position { + // `{Self}` is allowed + Position::ArgumentNamed(s) if s == "Self" => (), + // `{ThisTraitsName}` is allowed + Position::ArgumentNamed(s) if s == name => (), + // So is `{A}` if A is a type parameter + Position::ArgumentNamed(s) => match types.iter().find(|t| { + t.name == s + }) { + Some(_) => (), + None => { + span_err!(tcx.sess, span, E0230, + "there is no type parameter \ + {} on trait {}", + s, name); + result = Err(ErrorReported); + } + }, + // `{:1}` and `{}` are not to be used + Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => { + span_err!(tcx.sess, span, E0231, + "only named substitution \ + parameters are allowed"); result = Err(ErrorReported); } - }, - // `{:1}` and `{}` are not to be used - Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => { - span_err!(tcx.sess, span, E0231, - "only named substitution \ - parameters are allowed"); - result = Err(ErrorReported); } } } - } - result + result + }) } pub fn format(&self, @@ -280,28 +285,30 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { trait_ref.substs.type_for_def(param).to_string()) }).collect::>(); - let parser = Parser::new(&self.0); - parser.map(|p| { - match p { - Piece::String(s) => s, - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(s) { - Some(val) => val, - None if s == name => { - &trait_str + self.0.with(|str| { + let parser = Parser::new(str); + parser.map(|p| { + match p { + Piece::String(s) => s, + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => match generic_map.get(s) { + Some(val) => val, + None if s == name => { + &trait_str + } + None => { + bug!("broken on_unimplemented {:?} for {:?}: \ + no argument matching {:?}", + self.0, trait_ref, s) + } + }, + _ => { + bug!("broken on_unimplemented {:?} - bad \ + format arg", self.0) } - None => { - bug!("broken on_unimplemented {:?} for {:?}: \ - no argument matching {:?}", - self.0, trait_ref, s) - } - }, - _ => { - bug!("broken on_unimplemented {:?} - bad \ - format arg", self.0) } } - } - }).collect() + }).collect() + }) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index b233156cf7fc6..2cb76f7cc7f30 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1240,7 +1240,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn consider_optimizing String>(&self, msg: T) -> bool { let cname = self.crate_name(LOCAL_CRATE).as_str(); - self.sess.consider_optimizing(&cname, msg) + cname.with(|str| self.sess.consider_optimizing(str, msg)) } pub fn lang_items(self) -> Rc { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 0fecb5314bf44..beeec62d62b37 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -111,14 +111,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(extern_crate_def_id) = opt_extern_crate { self.push_item_path(buffer, extern_crate_def_id); } else { - buffer.push(&self.crate_name(cnum).as_str()); + self.crate_name(cnum).with_str(|str| buffer.push(str)); } } } RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. - buffer.push(&self.original_crate_name(cnum).as_str()); + self.original_crate_name(cnum).with_str(|str| buffer.push(str)); } } } @@ -139,12 +139,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match *self.extern_crate(cur_def) { Some(ref extern_crate) if extern_crate.direct => { self.push_item_path(buffer, extern_crate.def_id); - cur_path.iter().rev().map(|segment| buffer.push(&segment)).count(); + cur_path.iter() + .rev() + .map(|segment| segment.with(|str| buffer.push(str))) + .count(); return true; } None => { - buffer.push(&self.crate_name(cur_def.krate).as_str()); - cur_path.iter().rev().map(|segment| buffer.push(&segment)).count(); + self.crate_name(cur_def.krate).with_str(|str| buffer.push(str)); + cur_path.iter() + .rev() + .map(|segment| segment.with(|str| buffer.push(str))) + .count(); return true; } _ => {}, @@ -214,7 +220,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::GlobalMetaData(..) => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); - buffer.push(&data.as_interned_str()); + data.as_interned_str().with(|str| buffer.push(str)); } DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.parent_def_id(def_id).unwrap(); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 329dc6b502598..c075225159e90 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2762,12 +2762,6 @@ impl_stable_hash_for!(struct self::SymbolName { name }); -impl Deref for SymbolName { - type Target = str; - - fn deref(&self) -> &str { &self.name } -} - impl fmt::Display for SymbolName { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.name, fmt) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b124872ba12ca..45a4ef8858c9c 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1337,10 +1337,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out: &mut String) { match loan_path.kind { LpUpvar(ty::UpvarId { var_id: id, closure_expr_id: _ }) => { - out.push_str(&self.tcx.hir.name(self.tcx.hir.hir_to_node_id(id)).as_str()); + let name = self.tcx.hir.name(self.tcx.hir.hir_to_node_id(id)); + name.with_str(|str| out.push_str(str)); } LpVar(id) => { - out.push_str(&self.tcx.hir.name(id).as_str()); + self.tcx.hir.name(id).with_str(|str| out.push_str(str)); } LpDowncast(ref lp_base, variant_def_id) => { @@ -1356,7 +1357,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { match fname { mc::NamedField(fname) => { out.push('.'); - out.push_str(&fname.as_str()); + fname.with_str(|str| out.push_str(str)); } mc::PositionalField(idx) => { out.push('.'); diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index ddee122d0a6bd..6023038c9d812 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { let name = path1.node; // Skip anything that looks like `_foo` - if name.as_str().starts_with("_") { + if name.with_str(|str| str.starts_with("_")) { return } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 81cd63b5407c3..996b84e882fc5 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -317,7 +317,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, ConstEvalErr { span: e.span, kind: LayoutError(err) } }) }; - match &tcx.item_name(def_id)[..] { + match &*tcx.item_name(def_id).to_string() { "size_of" => { let size = layout_of(substs.type_at(0))?.size.bytes(); return Ok(mk_const(Integral(Usize(ConstUsize::new(size, @@ -613,14 +613,14 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, } } LitKind::Float(n, fty) => { - parse_float(&n.as_str(), fty).map(Float) + n.with_str(|str| parse_float(str, fty).map(Float)) } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - parse_float(&n.as_str(), fty).map(Float) + n.with_str(|str| parse_float(str, fty).map(Float)) } LitKind::Bool(b) => Ok(Bool(b)), LitKind::Char(c) => Ok(Char(c)), diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index cfbb9623f7dc9..8869cfaf61cd5 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -111,7 +111,7 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result { match *value { ConstVal::Float(ref x) => write!(f, "{}", x), ConstVal::Integral(ref i) => write!(f, "{}", i), - ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]), + ConstVal::Str(ref s) => write!(f, "{}", s), ConstVal::ByteStr(b) => write!(f, "{:?}", b.data), ConstVal::Bool(b) => write!(f, "{:?}", b), ConstVal::Char(c) => write!(f, "{:?}", c), diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5fa823659287a..f5eaa2b4a9130 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -766,7 +766,7 @@ impl RustcDefaultCalls { // specifically allowing the crt-static cfg and that's // it, this is intended to get into Cargo and then go // through to build scripts. - let value = value.as_ref().map(|s| s.as_str()); + let value = value.as_ref().map(|s| s.to_string()); let value = value.as_ref().map(|s| s.as_ref()); if name != "target_feature" || value != Some("crt-static") { if !allow_unstable_cfg && gated_cfg.is_some() { diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index acbd3e0d63dde..aa937ae3ad903 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { let dep_node = match dep_node_interned { None => def_path_hash.to_dep_node(DepKind::Hir), Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_path_hash) { + match n.with_str(|str| DepNode::from_label_string(str, def_path_hash)) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -143,7 +143,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_path_hash) { + match n.with_str(|str| DepNode::from_label_string(str, def_path_hash)) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index b17503137f508..cff8a4749fecb 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, &item); - return Some(self.resolve_labels(&item, value.as_str().as_ref())); + return Some(value.with_str(|str| self.resolve_labels(&item, str))); } } None @@ -323,7 +323,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(EXCEPT) { let value = expect_associated_value(self.tcx, &item); - return self.resolve_labels(&item, value.as_str().as_ref()); + return value.with_str(|str| self.resolve_labels(&item, str)); } } // if no `label` or `except` is given, only the node's group are asserted diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 49f14e8484f3a..87ff5cffe1284 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -17,6 +17,7 @@ use syntax::abi::Abi; use syntax::ast; use syntax::attr; use syntax_pos::Span; +use syntax_pos::symbol::Symbol; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::FnKind; @@ -54,15 +55,18 @@ pub struct NonCamelCaseTypes; impl NonCamelCaseTypes { fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) { fn is_camel_case(name: ast::Name) -> bool { - let name = name.as_str(); - if name.is_empty() { - return true; - } - let name = name.trim_matches('_'); + name.with_str(|name| { + if name.is_empty() { + return true; + } + let name = name.trim_matches('_'); - // start with a non-lowercase letter rather than non-uppercase - // ones (some scripts don't have a concept of upper/lowercase) - !name.is_empty() && !name.chars().next().unwrap().is_lowercase() && !name.contains('_') + // start with a non-lowercase letter rather than non-uppercase + // ones (some scripts don't have a concept of upper/lowercase) + !name.is_empty() + && !name.chars().next().unwrap().is_lowercase() + && !name.contains('_') + }) } fn to_camel_case(s: &str) -> String { @@ -79,7 +83,7 @@ impl NonCamelCaseTypes { } if !is_camel_case(name) { - let c = to_camel_case(&name.as_str()); + let c = name.with_str(|str| to_camel_case(str)); let m = if c.is_empty() { format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name) } else { @@ -173,7 +177,7 @@ impl NonSnakeCase { words.join("_") } - fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option) { + fn check_snake_case(&self, cx: &LateContext, sort: &str, name: Symbol, span: Option) { fn is_snake_case(ident: &str) -> bool { if ident.is_empty() { return true; @@ -195,21 +199,23 @@ impl NonSnakeCase { }) } - if !is_snake_case(name) { - let sc = NonSnakeCase::to_snake_case(name); - let msg = if sc != name { - format!("{} `{}` should have a snake case name such as `{}`", - sort, - name, - sc) - } else { - format!("{} `{}` should have a snake case name", sort, name) - }; - match span { - Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg), - None => cx.lint(NON_SNAKE_CASE, &msg), + name.with_str(|name| { + if !is_snake_case(name) { + let sc = NonSnakeCase::to_snake_case(name); + let msg = if sc != name { + format!("{} `{}` should have a snake case name such as `{}`", + sort, + name, + sc) + } else { + format!("{} `{}` should have a snake case name", sort, name) + }; + match span { + Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg), + None => cx.lint(NON_SNAKE_CASE, &msg), + } } - } + }) } } @@ -226,9 +232,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { .find(|at| at.check_name("crate_name")) .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { - self.check_snake_case(cx, "crate", name, None); + self.check_snake_case(cx, "crate", Symbol::intern(name), None); } else if let Some((attr, name)) = attr_crate_name { - self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span)); + self.check_snake_case(cx, "crate", name, Some(attr.span)); } } @@ -237,7 +243,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { self.check_snake_case( cx, "lifetime", - &ld.lifetime.name.name().as_str(), + ld.lifetime.name.name(), Some(ld.lifetime.span) ); } @@ -254,10 +260,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { FnKind::Method(name, ..) => { match method_context(cx, id) { MethodLateContext::PlainImpl => { - self.check_snake_case(cx, "method", &name.as_str(), Some(span)) + self.check_snake_case(cx, "method", name, Some(span)) } MethodLateContext::TraitAutoImpl => { - self.check_snake_case(cx, "trait method", &name.as_str(), Some(span)) + self.check_snake_case(cx, "trait method", name, Some(span)) } _ => (), } @@ -267,7 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { if abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() { return; } - self.check_snake_case(cx, "function", &name.as_str(), Some(span)) + self.check_snake_case(cx, "function", name, Some(span)) } FnKind::Closure(_) => (), } @@ -275,7 +281,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemMod(_) = it.node { - self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span)); + self.check_snake_case(cx, "module", it.name, Some(it.span)); } } @@ -283,17 +289,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref names)) = item.node { self.check_snake_case(cx, "trait method", - &item.name.as_str(), + item.name, Some(item.span)); for name in names { - self.check_snake_case(cx, "variable", &name.node.as_str(), Some(name.span)); + self.check_snake_case(cx, "variable", name.node, Some(name.span)); } } } fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { if let &PatKind::Binding(_, _, ref path1, _) = &p.node { - self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span)); + self.check_snake_case(cx, "variable", path1.node, Some(p.span)); } } @@ -304,7 +310,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { _: &hir::Generics, _: ast::NodeId) { for sf in s.fields() { - self.check_snake_case(cx, "structure field", &sf.name.as_str(), Some(sf.span)); + self.check_snake_case(cx, "structure field", sf.name, Some(sf.span)); } } } @@ -320,9 +326,9 @@ pub struct NonUpperCaseGlobals; impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) { - if name.as_str().chars().any(|c| c.is_lowercase()) { - let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase(); - if name != &*uc { + if name.with_str(|str| str.chars().any(|c| c.is_lowercase())) { + let uc = name.with_str(|str| NonSnakeCase::to_snake_case(str).to_uppercase()); + if name.with_str(|str| str != &*uc) { cx.span_lint(NON_UPPER_CASE_GLOBALS, span, &format!("{} `{}` should have an upper case name such as `{}`", diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index c109a47f79867..b39ce59bdf0a7 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -186,8 +186,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => { match t { - ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), - ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), + ast::FloatTy::F32 => + v.with_str(|str| str.parse().map(f32::is_infinite)), + ast::FloatTy::F64 => + v.with_str(|str| str.parse().map(f64::is_infinite)), } } _ => bug!(), diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 4e066ecf999e3..b656f94e1832e 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { // check for #[must_use="..."] if let Some(s) = attr.value_str() { msg.push_str(": "); - msg.push_str(&s.as_str()); + s.with_str(|str| msg.push_str(str)); } cx.span_lint(UNUSED_MUST_USE, sp, &msg); return true; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 58453066cf34b..a7c5ecf75c6b1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -131,7 +131,7 @@ impl<'a> CrateLoader<'a> { // `source` stores paths which are normalized which may be different // from the strings on the command line. let source = &self.cstore.get_crate_data(cnum).source; - if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { + if let Some(locs) = name.with_str(|str| self.sess.opts.externs.get(str)) { let found = locs.iter().any(|l| { let l = fs::canonicalize(l).ok(); source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || @@ -957,9 +957,9 @@ impl<'a> CrateLoader<'a> { // We have an allocator. We detect separately what kind it is, to allow for some // flexibility in misconfiguration. let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess); - let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind") - .map(Symbol::as_str); - let kind_str = kind_interned + let kind_string = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind") + .map(|s| s.to_string()); + let kind_str = kind_string .as_ref() .map(|s| s as &str); let alloc_kind = match kind_str { @@ -1062,7 +1062,9 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { debug!("resolving extern crate stmt. ident: {} rename: {:?}", item.ident, rename); let rename = match rename { Some(rename) => { - validate_crate_name(Some(self.sess), &rename.as_str(), Some(item.span)); + rename.with_str(|str| { + validate_crate_name(Some(self.sess), str, Some(item.span)) + }); rename } None => item.ident.name, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 955648208cd8b..c62be07a29f61 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -489,7 +489,7 @@ impl CrateStore for cstore::CStore { .insert(local_span, (name.to_string(), data.get_span(id.index, sess))); LoadedMacro::MacroDef(ast::Item { - ident: ast::Ident::from_str(&name), + ident: ast::Ident::with_empty_ctxt(name.as_symbol()), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index fb4a73891a34e..8ae6cabcb5a2b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -40,7 +40,7 @@ use rustc_data_structures::indexed_vec::Idx; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::codemap; -use syntax::symbol::{InternedString, Symbol}; +use syntax::symbol::InternedString; use syntax::ext::base::MacroKind; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; @@ -488,12 +488,12 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), - name: Symbol::intern(&self.item_name(index)), + name: self.item_name(index).as_symbol(), fields: item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - name: Symbol::intern(&self.item_name(index)), + name: self.item_name(index).as_symbol(), vis: f.visibility.decode(self) } }).collect(), @@ -681,7 +681,8 @@ impl<'a, 'tcx> CrateMetadata { if let Some(def) = self.get_def(child_index) { callback(def::Export { def, - ident: Ident::from_str(&self.item_name(child_index)), + ident: Ident::with_empty_ctxt(self.item_name(child_index) + .as_symbol()), vis: self.get_visibility(child_index), span: self.entry(child_index).span.decode((self, sess)), is_import: false, @@ -700,7 +701,7 @@ impl<'a, 'tcx> CrateMetadata { let span = child.span.decode((self, sess)); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { - let ident = Ident::from_str(&name); + let ident = Ident::with_empty_ctxt(name.as_symbol()); let vis = self.get_visibility(child_index); let is_import = false; callback(def::Export { def, ident, vis, span, is_import }); @@ -838,7 +839,7 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssociatedItem { - name: Symbol::intern(&name), + name: name.as_symbol(), kind, vis: item.visibility.decode(self), defaultness: container.defaultness(), @@ -903,7 +904,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id) .children .decode(self) - .map(|index| Symbol::intern(&self.item_name(index))) + .map(|index| self.item_name(index).as_symbol()) .collect() } diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 6fafde0d09c16..bc79e0d342ddd 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -22,7 +22,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { for attr in tcx.hir.krate().attrs.iter() { if attr.path == "link_args" { if let Some(linkarg) = attr.value_str() { - collector.add_link_args(&linkarg.as_str()); + linkarg.with_str(|str| collector.add_link_args(str)); } } } @@ -49,7 +49,7 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector { // First, add all of the custom #[link_args] attributes for m in it.attrs.iter().filter(|a| a.check_name("link_args")) { if let Some(linkarg) = m.value_str() { - self.add_link_args(&linkarg.as_str()); + linkarg.with_str(|str| self.add_link_args(str)); } } } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 90c469eea843d..c15f12dc187c0 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -424,7 +424,7 @@ impl<'a> Context<'a> { // must be loaded via -L plus some filtering. if self.hash.is_none() { self.should_match_name = false; - if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { + if let Some(s) = self.crate_name.with_str(|str| self.sess.opts.externs.get(str)) { return self.find_commandline_library(s.iter()); } self.should_match_name = true; @@ -540,7 +540,7 @@ impl<'a> Context<'a> { crate_name, pd.display(), pr.display(), - padding=8 + crate_name.len())) + padding=8 + crate_name.with(|str| str.len()))) } &(&Some((ref p, _)), &None) | &(&None, &Some((ref p, _))) => { Some(format!("\ncrate `{}`: {}", crate_name, p.display())) diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index cc332acb5b08e..1e4034dcceefb 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { }; let kind = items.iter().find(|k| { k.check_name("kind") - }).and_then(|a| a.value_str()).map(Symbol::as_str); + }).and_then(|a| a.value_str()).map(|s| s.to_string()); let kind = match kind.as_ref().map(|s| &s[..]) { Some("static") => cstore::NativeStatic, Some("static-nobundle") => cstore::NativeStaticNobundle, @@ -114,7 +114,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { impl<'a, 'tcx> Collector<'a, 'tcx> { fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { - if lib.name.as_str().is_empty() { + if lib.name.with_str(|str| str.is_empty()) { match span { Some(span) => { struct_span_err!(self.tcx.sess, span, E0454, diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 3e0ccc7d07260..916fb562f6ab6 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -217,9 +217,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } _ => None }; - let intrinsic = intrinsic.as_ref().map(|s| &s[..]); let fun = unpack!(block = this.as_local_operand(block, fun)); - if intrinsic == Some("move_val_init") { + if intrinsic.map(|s| s.with(|str| str == "move_val_init")).unwrap_or(false) { // `move_val_init` has "magic" semantics - the second argument is // always evaluated "directly" into the first one. diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index a37cf41baaba3..3656bf1fe9b94 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -228,8 +228,8 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeEvaluator { ) -> EvalResult<'tcx> { let substs = instance.substs; - let intrinsic_name = &ecx.tcx.item_name(instance.def_id())[..]; - match intrinsic_name { + let intrinsic_name = ecx.tcx.item_name(instance.def_id()).to_string(); + match &*intrinsic_name { "min_align_of" => { let elem_ty = substs.type_at(0); let elem_align = ecx.layout_of(elem_ty)?.align.abi(); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 89d0e91a7ec86..1062809e6129c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { Bool(b) => PrimVal::from_bool(b), Char(c) => PrimVal::from_char(c), - Str(ref s) => return self.str_to_value(s), + Str(ref s) => return s.with(|str| self.str_to_value(str)), ByteStr(ref bs) => { let ptr = self.memory.allocate_cached(bs.data); diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index c3fb126ea1822..452d6066258d5 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -165,7 +165,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { let attributes = tcx.get_attrs(def_id); if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") { - if let Some(linkage) = linkage_by_name(&name.as_str()) { + if let Some(linkage) = name.with_str(|str| linkage_by_name(str)) { Some(linkage) } else { let span = tcx.hir.span_if_local(def_id); @@ -427,7 +427,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { // some_crate:: if !(self.omit_local_crate_name && def_id.is_local()) { - output.push_str(&self.tcx.crate_name(def_path.krate).as_str()); + self.tcx.crate_name(def_path.krate).with_str(|str| output.push_str(str)); output.push_str("::"); } @@ -467,8 +467,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { for projection in projections { let projection = projection.skip_binder(); - let name = &self.tcx.associated_item(projection.item_def_id).name.as_str(); - output.push_str(name); + let name = self.tcx.associated_item(projection.item_def_id).name; + name.with_str(|str| output.push_str(str)); output.push_str("="); self.push_type_name(projection.ty, output); output.push_str(", "); diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 55c194ae7a584..12118de0096dd 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -144,7 +144,7 @@ pub trait CodegenUnitExt<'tcx> { } fn work_product_id(&self) -> WorkProductId { - WorkProductId::from_cgu_name(self.name()) + self.name().with(|str| WorkProductId::from_cgu_name(str)) } fn items_in_deterministic_order<'a>(&self, @@ -220,7 +220,9 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { - merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str()); + tcx.crate_name.with_str(|str| { + merge_codegen_units(&mut initial_partitioning, count, str) + }); debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } @@ -631,7 +633,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut mod_path = String::with_capacity(64); let def_path = tcx.def_path(def_id); - mod_path.push_str(&tcx.crate_name(def_path.krate).as_str()); + tcx.crate_name(def_path.krate).with_str(|str| mod_path.push_str(str)); for part in tcx.def_path(def_id) .data @@ -643,7 +645,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }) { mod_path.push_str("-"); - mod_path.push_str(&part.data.as_interned_str()); + part.data.as_interned_str().with(|str| mod_path.push_str(str)); } if volatile { @@ -669,7 +671,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("CodegenUnit {}:", cgu.name()); for (trans_item, linkage) in cgu.items() { - let symbol_name = trans_item.symbol_name(tcx); + let symbol_name = trans_item.symbol_name(tcx).to_string(); let symbol_hash_start = symbol_name.rfind('h'); let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index e9ba5de3cc694..870afa4f836cf 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -439,7 +439,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { struct_span_err!( tcx.sess, source_info.span, E0133, "{} requires unsafe function or block", description) - .span_label(source_info.span, &description[..]) + .span_label(source_info.span, description) .emit(); } UnsafetyViolationKind::ExternStatic(lint_node_id) => { @@ -447,7 +447,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { lint_node_id, source_info.span, &format!("{} requires unsafe function or \ - block (error E0133)", &description[..])); + block (error E0133)", description)); } UnsafetyViolationKind::BorrowPacked(lint_node_id) => { if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) { @@ -457,7 +457,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { lint_node_id, source_info.span, &format!("{} requires unsafe function or \ - block (error E0133)", &description[..])); + block (error E0133)", description)); } } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f0871bb188d49..273f1b6654483 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -732,7 +732,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Abi::RustIntrinsic | Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); - match &self.tcx.item_name(def_id)[..] { + self.tcx.item_name(def_id).with(|str| match str { "size_of" | "min_align_of" => is_const_fn = Some(def_id), name if name.starts_with("simd_shuffle") => { @@ -740,7 +740,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } _ => {} - } + }) } _ => { if self.tcx.is_const_fn(def_id) { diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 8a4ec03b20efc..6f3119db1ae4a 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -71,7 +71,9 @@ pub fn load_plugins(sess: &Session, match plugin.name() { Some(name) if !plugin.is_value_str() => { let args = plugin.meta_item_list().map(ToOwned::to_owned); - loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default()); + name.with_str(|str| { + loader.load_plugin(plugin.span, str, args.unwrap_or_default()) + }); }, _ => call_malformed_plugin_attribute(sess, attr.span), } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 3f74093241d29..d06b92d876a9e 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -129,7 +129,7 @@ impl<'a> Registry<'a> { #[unstable(feature = "rustc_private", issue = "27812")] #[rustc_deprecated(since = "1.15.0", reason = "replaced by macros 1.1 (RFC 1861)")] pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) { - assert!(name.as_str().starts_with("derive_")); + name.with_str(|str| assert!(str.starts_with("derive_"))); self.whitelisted_custom_derives.push(name); self.register_syntax_extension(name, extension); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 72017ec215f82..7704f1b8d72e6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -42,7 +42,6 @@ use syntax::ext::tt::macro_rules; use syntax::parse::token::{self, Token}; use syntax::std_inject::injected_crate_name; use syntax::symbol::keywords; -use syntax::symbol::Symbol; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -557,7 +556,7 @@ impl<'a> Resolver<'a> { Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; - let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name)); + let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol()); let module = self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP)); self.extern_module_map.insert((def_id, macros_only), module); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b49d9d2c7cf11..de0c305bf1c39 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -135,11 +135,11 @@ enum ResolutionError<'a> { /// error E0409: variable `{}` is bound in inconsistent ways within the same match arm VariableBoundWithDifferentMode(Name, Span), /// error E0415: identifier is bound more than once in this parameter list - IdentifierBoundMoreThanOnceInParameterList(&'a str), + IdentifierBoundMoreThanOnceInParameterList(Symbol), /// error E0416: identifier is bound more than once in the same pattern - IdentifierBoundMoreThanOnceInSamePattern(&'a str), + IdentifierBoundMoreThanOnceInSamePattern(Symbol), /// error E0426: use of undeclared label - UndeclaredLabel(&'a str, Option), + UndeclaredLabel(Symbol, Option), /// error E0429: `self` imports are only allowed within a { } list SelfImportsOnlyAllowedWithin, /// error E0430: `self` import can only appear once in the list @@ -2414,7 +2414,7 @@ impl<'a> Resolver<'a> { self, ident.span, ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( - &ident.node.name.as_str()) + ident.node.name) ); } Some(..) if pat_src == PatternSource::FnParam => { @@ -2423,7 +2423,7 @@ impl<'a> Resolver<'a> { self, ident.span, ResolutionError::IdentifierBoundMoreThanOnceInParameterList( - &ident.node.name.as_str()) + ident.node.name) ); } Some(..) if pat_src == PatternSource::Match => { @@ -3320,7 +3320,7 @@ impl<'a> Resolver<'a> { let name = path[path.len() - 1].node.name; // Make sure error reporting is deterministic. names.sort_by_key(|name| name.as_str()); - match find_best_match_for_name(names.iter(), &name.as_str(), None) { + match name.with_str(|str| find_best_match_for_name(names.iter(), str, None)) { Some(found) if found != name => Some(found), _ => None, } @@ -3370,12 +3370,14 @@ impl<'a> Resolver<'a> { // the closest match let close_match = self.search_label(label.node, |rib, ident| { let names = rib.bindings.iter().map(|(id, _)| &id.name); - find_best_match_for_name(names, &*ident.name.as_str(), None) + ident.name.with_str(|str| { + find_best_match_for_name(names, str, None) + }) }); self.record_def(expr.id, err_path_resolution()); resolve_error(self, label.span, - ResolutionError::UndeclaredLabel(&label.node.name.as_str(), + ResolutionError::UndeclaredLabel(label.node.name, close_match)); } Some(def @ Def::Label(_)) => { @@ -3979,7 +3981,7 @@ fn names_to_string(idents: &[SpannedIdent]) -> String { if i > 0 { result.push_str("::"); } - result.push_str(&ident.node.name.as_str()); + ident.node.name.with_str(|str| result.push_str(str)); } result } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 260a0cd7cd733..ce5dbb0f67f50 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -636,7 +636,9 @@ impl<'a> Resolver<'a> { format!("cannot find derive macro `{}` in this scope", ident), }; let mut err = self.session.struct_span_err(span, &msg); - self.suggest_macro_name(&ident.name.as_str(), kind, &mut err, span); + ident.name.with_str(|str| { + self.suggest_macro_name(str, kind, &mut err, span); + }); err.emit(); }, _ => {}, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e249ecfca588e..f785d6f918f1f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -766,7 +766,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } }); let lev_suggestion = - match find_best_match_for_name(names, &ident.name.as_str(), None) { + match ident.name.with_str(|str| find_best_match_for_name(names, str, None)) { Some(name) => format!(". Did you mean to use `{}`?", name), None => "".to_owned(), }; diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 93fb22a2dc0c9..703ac1c2af3e1 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -864,11 +864,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { for attr in attrs { if attr.check_name("doc") { if let Some(val) = attr.value_str() { - if attr.is_sugared_doc { - result.push_str(&strip_doc_comment_decoration(&val.as_str())); + val.with_str(|str| if attr.is_sugared_doc { + result.push_str(&strip_doc_comment_decoration(str)); } else { - result.push_str(&val.as_str()); - } + result.push_str(str); + }); result.push('\n'); } } diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs index ef76fece088fe..1177e15113828 100644 --- a/src/librustc_trans/asm.rs +++ b/src/librustc_trans/asm.rs @@ -86,7 +86,7 @@ pub fn trans_inline_asm<'a, 'tcx>( AsmDialect::Intel => llvm::AsmDialect::Intel, }; - let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap(); + let asm = ia.asm.with_str(|str| CString::new(str.as_bytes()).unwrap()); let constraint_cstr = CString::new(all_constraints).unwrap(); let r = bcx.inline_asm_call( asm.as_ptr(), @@ -121,7 +121,7 @@ pub fn trans_inline_asm<'a, 'tcx>( pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ga: &hir::GlobalAsm) { - let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap(); + let asm = ga.asm.with_str(|str| CString::new(str.as_bytes()).unwrap()); unsafe { llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr()); } diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 745aa0da82900..311c33606d16b 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -104,11 +104,11 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe for attr in attrs { if attr.check_name("target_feature") { if let Some(val) = attr.value_str() { - for feat in val.as_str().split(",").map(|f| f.trim()) { + val.with_str(|str| for feat in str.split(",").map(|f| f.trim()) { if !feat.is_empty() && !feat.contains('\0') { target_features.push(feat.to_string()); } - } + }) } } else if attr.check_name("cold") { Attribute::Cold.apply_llfn(Function, llfn); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index ec1c7e16c71f0..4755e32628d21 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -399,7 +399,7 @@ fn link_rlib<'a>(sess: &'a Session, NativeLibraryKind::NativeFramework | NativeLibraryKind::NativeUnknown => continue, } - ab.add_native_library(&lib.name.as_str()); + lib.name.with_str(|str| ab.add_native_library(str)); } // After adding all files to the archive, we need to update the @@ -1025,13 +1025,13 @@ fn add_local_native_libraries(cmd: &mut Linker, let search_path = archive_search_paths(sess); for lib in relevant_libs { - match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), - NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), - NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), - NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&lib.name.as_str(), + lib.name.with_str(|str| match lib.kind { + NativeLibraryKind::NativeUnknown => cmd.link_dylib(str), + NativeLibraryKind::NativeFramework => cmd.link_framework(str), + NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(str), + NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(str, &search_path) - } + }) } } @@ -1343,23 +1343,23 @@ fn add_upstream_native_libraries(cmd: &mut Linker, if !relevant_lib(sess, &lib) { continue } - match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), - NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), + lib.name.with_str(|str| match lib.kind { + NativeLibraryKind::NativeUnknown => cmd.link_dylib(str), + NativeLibraryKind::NativeFramework => cmd.link_framework(str), NativeLibraryKind::NativeStaticNobundle => { // Link "static-nobundle" native libs only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically // or is an rlib already included via some other dylib crate, the symbols from // native libs will have already been included in that dylib. if data[cnum.as_usize() - 1] == Linkage::Static { - cmd.link_staticlib(&lib.name.as_str()) + cmd.link_staticlib(str) } }, // ignore statically included native libraries here as we've // already included them when we included the rust library // previously NativeLibraryKind::NativeStatic => {} - } + }) } } } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index fa6fe2e9e93ef..df629dceb4b77 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -92,10 +92,10 @@ pub fn provide(providers: &mut Providers) { tcx.hir.local_def_id(node_id) }) .map(|def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + let name = tcx.symbol_name(Instance::mono(tcx, def_id)).to_string(); let export_level = export_level(tcx, def_id); debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + (name, Some(def_id), export_level) }) .collect(); @@ -170,7 +170,7 @@ pub fn provide_extern(providers: &mut Providers) { .exported_symbol_ids(cnum) .iter() .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + let name = tcx.symbol_name(Instance::mono(tcx, def_id)).to_string(); let export_level = if compiler_builtins_and_binaryen && tcx.contains_extern_indicator(def_id) { SymbolExportLevel::C @@ -193,7 +193,7 @@ pub fn provide_extern(providers: &mut Providers) { export_level(tcx, def_id) }; debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + (name, Some(def_id), export_level) }) .collect(); diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 825f306499a7c..27d8af4bc825a 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -369,7 +369,7 @@ impl SymbolPathBuffer { result: String::with_capacity(64), temp_buf: String::with_capacity(16) }; - result.result.push_str(&symbol.name); + symbol.name.with(|str| result.result.push_str(str)); result } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 680821d6d681e..baa30c3148919 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -510,11 +510,11 @@ pub fn set_link_section(ccx: &CrateContext, llval: ValueRef, attrs: &[ast::Attribute]) { if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") { - if contains_null(§.as_str()) { + if sect.with_str(|str| contains_null(str)) { ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §)); } unsafe { - let buf = CString::new(sect.as_str().as_bytes()).unwrap(); + let buf = sect.with_str(|str| CString::new(str.as_bytes()).unwrap()); llvm::LLVMSetSection(llval, buf.as_ptr()); } } @@ -1076,7 +1076,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); - output.push_str(&cgu_name); + cgu_name.with(|str| output.push_str(str)); let linkage_abbrev = match linkage { Linkage::External => "External", diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 0a0f2615a1bd1..aca4f1649f4e2 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -60,7 +60,7 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty)); let llptrty = ccx.layout_of(fn_ptr_ty).llvm_type(ccx); - let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) { + let llfn = if let Some(llfn) = sym.name.with(|str| declare::get_declared_value(ccx, str)) { // This is subtle and surprising, but sometimes we have to bitcast // the resulting fn pointer. The reason has to do with external // functions. If you have two crates that both bind the same C @@ -92,7 +92,7 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn } } else { - let llfn = declare::declare_fn(ccx, &sym, fn_ty); + let llfn = sym.name.with(|str| declare::declare_fn(ccx, str, fn_ty)); assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index b1bdee3fa5fc5..c25354d5b52e0 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -190,11 +190,12 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va if let Some(&llval) = cx.const_cstr_cache().borrow().get(&s) { return llval; } - - let sc = llvm::LLVMConstStringInContext(cx.llcx(), - s.as_ptr() as *const c_char, - s.len() as c_uint, - !null_terminated as Bool); + let sc = s.with(|s| { + llvm::LLVMConstStringInContext(cx.llcx(), + s.as_ptr() as *const c_char, + s.len() as c_uint, + !null_terminated as Bool) + }); let sym = cx.generate_local_symbol_name("str"); let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{ bug!("symbol `{}` is already defined", sym); @@ -211,7 +212,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va // NB: Do not use `do_spill_noroot` to make this into a constant string, or // you will be kicked off fast isel. See issue #4352 for an example of this. pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef { - let len = s.len(); + let len = s.with(|str| str.len()); let cs = consts::ptrcast(C_cstr(cx, s, false), cx.layout_of(cx.tcx().mk_str()).llvm_type(cx).ptr_to()); C_fat_ptr(cx, cs, C_usize(cx, len as u64)) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index f9fbcebd32e72..b9b3eb07d4336 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -125,11 +125,11 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { .contains_key(&MonoItem::Static(id)); assert!(!defined_in_current_codegen_unit); - if declare::get_declared_value(ccx, &sym[..]).is_some() { + if sym.name.with(|str| declare::get_declared_value(ccx, str).is_some()) { span_bug!(span, "trans: Conflicting symbol names for static?"); } - let g = declare::define_global(ccx, &sym[..], llty).unwrap(); + let g = sym.name.with(|str| declare::define_global(ccx, str, llty).unwrap()); if !ccx.tcx().is_exported_symbol(def_id) { unsafe { @@ -151,7 +151,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // extern "C" fn() from being non-null, so we can't just declare a // static and call it a day. Some linkages (like weak) will make it such // that the static actually has a null value. - let linkage = match base::linkage_by_name(&name.as_str()) { + let linkage = match name.with_str(|str| base::linkage_by_name(str)) { Some(linkage) => linkage, None => { ccx.sess().span_fatal(span, "invalid linkage specified"); @@ -165,7 +165,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = declare::declare_global(ccx, &sym, llty2); + let g1 = sym.name.with(|str| declare::declare_global(ccx, str, llty2)); llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); // Declare an internal global `extern_with_linkage_foo` which @@ -175,7 +175,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // `extern_with_linkage_foo` will instead be initialized to // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&sym); + sym.name.with(|str| real_name.push_str(str)); let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{ ccx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym)) @@ -186,7 +186,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { } } else { // Generate an external declaration. - declare::declare_global(ccx, &sym, llty) + sym.name.with(|str| declare::declare_global(ccx, str, llty)) }; (g, attrs) @@ -207,7 +207,9 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? // FIXME(nagisa): investigate whether it can be changed into define_global - let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx)); + let g = sym.name.with(|str| { + declare::declare_global(ccx, str, ccx.layout_of(ty).llvm_type(ccx)) + }); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the // thread-local attribute locally if it was present remotely. If we diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index d5e71062f74d7..c89d6d7088ae3 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -365,10 +365,12 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo { let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(shared, - codegen_unit.name(), - &dctx, - shared.tcx.sess); + codegen_unit.name().with(|str| { + debuginfo::metadata::compile_unit_metadata(shared, + str, + &dctx, + shared.tcx.sess); + }); Some(dctx) } else { None diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 871f255951483..66d41c16c6771 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -792,7 +792,9 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, -> DIDescriptor { let mut name_in_debuginfo = match sess.local_crate_source_file { Some(ref path) => path.clone(), - None => PathBuf::from(&*scc.tcx().crate_name(LOCAL_CRATE).as_str()), + None => scc.tcx().crate_name(LOCAL_CRATE).with_str(|str| { + PathBuf::from(str) + }), }; // The OSX linker has an idiosyncrasy where it will ignore some debuginfo @@ -1234,7 +1236,9 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { self.layout, self.layout.fields.offset(0), self.layout.field(cx, 0).size); - name.push_str(&adt.variants[niche_variants.start].name.as_str()); + adt.variants[niche_variants.start].name.with_str(|str| { + name.push_str(str); + }); // Create the (singleton) list of descriptions of union members. vec![ @@ -1299,19 +1303,20 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, containing_scope: DIScope, span: Span) -> (DICompositeType, MemberDescriptionFactory<'tcx>) { - let variant_name = variant.name.as_str(); - let unique_type_id = debug_context(cx).type_map - .borrow_mut() - .get_unique_type_id_of_enum_variant( - cx, - layout.ty, - &variant_name); - - let metadata_stub = create_struct_stub(cx, - layout.ty, - &variant_name, - unique_type_id, - containing_scope); + let metadata_stub = variant.name.with_str(|variant_name| { + let unique_type_id = debug_context(cx).type_map + .borrow_mut() + .get_unique_type_id_of_enum_variant( + cx, + layout.ty, + variant_name); + + create_struct_stub(cx, + layout.ty, + variant_name, + unique_type_id, + containing_scope) + }); // If this is not a univariant enum, there is also the discriminant field. let (discr_offset, discr_arg) = match discriminant_info { @@ -1374,7 +1379,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .zip(&def.variants) .map(|(discr, v)| { let token = v.name.as_str(); - let name = CString::new(token.as_bytes()).unwrap(); + let name = token.with(|str| CString::new(str.as_bytes()).unwrap()); unsafe { llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), @@ -1399,7 +1404,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, type_metadata(cx, discr.to_ty(cx.tcx()), syntax_pos::DUMMY_SP); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); - let name = CString::new(discriminant_name.as_bytes()).unwrap(); + let name = discriminant_name.with(|str| CString::new(str.as_bytes()).unwrap()); let discriminant_type_metadata = unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 3f9ace151a389..9da67d3a61fee 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -390,7 +390,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, substs.types().zip(names).map(|(ty, name)| { let actual_type = cx.tcx().fully_normalize_associated_types_in(&ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(name.as_str().as_bytes()).unwrap(); + let name = name.with_str(|str| CString::new(str.as_bytes()).unwrap()); unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -480,7 +480,7 @@ pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, }; let align = cx.align_of(variable_type); - let name = CString::new(variable_name.as_str().as_bytes()).unwrap(); + let name = variable_name.with_str(|str| CString::new(str.as_bytes()).unwrap()); match (variable_access, &[][..]) { (DirectVariable { alloca }, address_operations) | (IndirectVariable {alloca, address_operations}, _) => { diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 47e2b8c461ca4..9631d9b4d1356 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -61,7 +61,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { data => data.as_interned_str() }; - let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let namespace_name = namespace_name.with(|str| CString::new(str.as_bytes()).unwrap()); let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 85467f5bfbd22..4d7528e2fc778 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -184,13 +184,13 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, qualified: bool, output: &mut String) { if qualified { - output.push_str(&cx.tcx().crate_name(def_id.krate).as_str()); + cx.tcx().crate_name(def_id.krate).with_str(|str| output.push_str(str)); for path_element in cx.tcx().def_path(def_id).data { output.push_str("::"); - output.push_str(&path_element.data.as_interned_str()); + path_element.data.as_interned_str().with(|str| output.push_str(str)); } } else { - output.push_str(&cx.tcx().item_name(def_id)); + cx.tcx().item_name(def_id).with(|str| output.push_str(str)); } } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 3cd60e7f1bc7f..a7f43b19cb11f 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -103,13 +103,14 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); - let name = &*tcx.item_name(def_id); + let name = tcx.item_name(def_id).to_string(); + let name = &*name; let llret_ty = ccx.layout_of(ret_ty).llvm_type(ccx); let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align); let simple = get_simple_intrinsic(ccx, name); - let llval = match name { + let llval = match &*name { _ if simple.is_some() => { bcx.call(simple.unwrap(), &args.iter().map(|arg| arg.immediate()).collect::>(), diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c4849c621e8d5..8359beccaf721 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -188,7 +188,9 @@ impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate { } fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { - back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str()); + trans.crate_name.with_str(|str| { + back::link::link_binary(sess, trans, outputs, str); + }); } fn dump_incremental_data(trans: &Self::TranslatedCrate) { diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 422b8210b3544..6cece20edcd87 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -459,10 +459,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Handle intrinsics old trans wants Expr's for, ourselves. let intrinsic = match def { Some(ty::InstanceDef::Intrinsic(def_id)) - => Some(bcx.tcx().item_name(def_id)), + => Some(bcx.tcx().item_name(def_id).to_string()), _ => None }; - let intrinsic = intrinsic.as_ref().map(|s| &s[..]); + let intrinsic = intrinsic.as_ref().map(|s| &**s); if intrinsic == Some("transmute") { let &(ref dest, target) = destination.as_ref().unwrap(); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index d836d796c4113..8b40530d61355 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -397,7 +397,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } if let Some((ref dest, target)) = *destination { let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic { - match &tcx.item_name(def_id)[..] { + tcx.item_name(def_id).with(|str| match str { "size_of" => { let llval = C_usize(self.ccx, self.ccx.size_of(substs.type_at(0)).bytes()); @@ -409,7 +409,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { Ok(Const::new(llval, tcx.types.usize)) } _ => span_bug!(span, "{:?} in constant", terminator.kind) - } + }) } else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) { (||{ assert_eq!(arg_vals.len(), 2); diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 917ff87a674b6..64be2198e75f6 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -266,7 +266,7 @@ pub fn trans_mir<'a, 'tcx: 'a>( } debug!("alloc: {:?} ({}) -> place", local, name); - let place = PlaceRef::alloca(&bcx, layout, &name.as_str()); + let place = name.with_str(|str| PlaceRef::alloca(&bcx, layout, str)); if dbg { let (scope, span) = mircx.debug_loc(decl.source_info); declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope, diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 31d8e092c4ae4..db9688bb05ab2 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -91,15 +91,15 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { debug!("symbol {}", &symbol_name); - match *self.as_mono_item() { + symbol_name.name.with(|symbol_name| match *self.as_mono_item() { MonoItem::Static(node_id) => { - predefine_static(ccx, node_id, linkage, visibility, &symbol_name); + predefine_static(ccx, node_id, linkage, visibility, symbol_name); } MonoItem::Fn(instance) => { - predefine_fn(ccx, instance, linkage, visibility, &symbol_name); + predefine_fn(ccx, instance, linkage, visibility, symbol_name); } MonoItem::GlobalAsm(..) => {} - } + }); debug!("END PREDEFINING '{} ({})' in cgu {}", self.to_string(ccx.tcx()), diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 122914fa40b52..baa76bda26427 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -221,8 +221,9 @@ impl TransCrate for MetadataOnlyTransCrate { if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { continue; } - let output_name = - out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str()); + let output_name = trans.0.crate_name.with_str(|str| { + out_filename(sess, crate_type, &outputs, str) + }); let mut compressed = trans.0.metadata_version.clone(); let metadata = if crate_type == CrateType::CrateTypeDylib { DeflateEncoder::new(&mut compressed, Compression::Fast) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4616b4cf80c97..f49f14db47d8c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -727,10 +727,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap(); let param_name = tcx.hir.ty_param_name(param_node_id); - self.one_bound_for_assoc_type(suitable_bounds, - ¶m_name.as_str(), - assoc_name, - span) + param_name.with_str(|str| { + self.one_bound_for_assoc_type(suitable_bounds, + str, + assoc_name, + span) + }) } @@ -845,10 +847,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { _ => { // Don't print TyErr to the user. if !ty.references_error() { - self.report_ambiguous_associated_type(span, - &ty.to_string(), - "Trait", - &assoc_name.as_str()); + assoc_name.with_str(|str| { + self.report_ambiguous_associated_type(span, + &ty.to_string(), + "Trait", + str); + }); } return (tcx.types.err, Def::Err); } @@ -892,10 +896,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty } else { let path_str = tcx.item_path_str(trait_def_id); - self.report_ambiguous_associated_type(span, - "Type", - &path_str, - &item_segment.name.as_str()); + item_segment.name.with_str(|str| { + self.report_ambiguous_associated_type(span, + "Type", + &path_str, + str) + }); return tcx.types.err; }; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 23243c3ad66c0..108ecf4489365 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -77,7 +77,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n))); - let name = it.name.as_str(); + let name = it.name.to_string(); let (n_tps, inputs, output) = if name.starts_with("atomic_") { let split : Vec<&str> = name.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic not correct format"); @@ -346,7 +346,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def_id = tcx.hir.local_def_id(it.id); let i_n_tps = tcx.generics_of(def_id).types.len(); - let name = it.name.as_str(); + let name = it.name.to_string(); let (n_tps, inputs, output) = match &*name { "simd_eq" | "simd_ne" | "simd_lt" | "simd_le" | "simd_gt" | "simd_ge" => { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 53bb0e577a4b6..c904fb1dcf2e4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1210,9 +1210,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } else { let best_name = { let names = applicable_close_candidates.iter().map(|cand| &cand.name); - find_best_match_for_name(names, - &self.method_name.unwrap().as_str(), - None) + self.method_name.unwrap().with_str(|str| { + find_best_match_for_name(names, + str, + None) + }) }.unwrap(); Ok(applicable_close_candidates .into_iter() @@ -1353,14 +1355,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn impl_or_trait_item(&self, def_id: DefId) -> Vec { if let Some(name) = self.method_name { if self.allow_similar_names { - let max_dist = max(name.as_str().len(), 3) / 3; - self.tcx.associated_items(def_id) - .filter(|x| { - let dist = lev_distance(&*name.as_str(), &x.name.as_str()); - Namespace::from(x.kind) == Namespace::Value && dist > 0 - && dist <= max_dist - }) - .collect() + name.with_str(|name| { + let max_dist = max(name.len(), 3) / 3; + self.tcx.associated_items(def_id) + .filter(|x| { + let dist = x.name.with_str(|x_name| lev_distance(name, x_name)); + Namespace::from(x.kind) == Namespace::Value && dist > 0 + && dist <= max_dist + }) + .collect() + }) } else { self.fcx .associated_item(def_id, name, Namespace::Value) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f29009c1973a2..45d9a17b87dae 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if actual.is_enum() { "variant" } else { - match (item_name.as_str().chars().next(), actual.is_fresh_ty()) { + match (item_name.with_str(|str| str.chars().next()), actual.is_fresh_ty()) { (Some(name), false) if name.is_lowercase() => { "function or associated item" } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a49c3549abdf..784ba79fbe0fb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3039,7 +3039,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); - find_best_match_for_name(names, &name, None) + name.with(|str| find_best_match_for_name(names, str, None)) } fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec { diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 5eb3e38d5b371..47c5e80ae5369 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -81,7 +81,7 @@ impl Cfg { }, MetaItemKind::List(ref items) => { let mut sub_cfgs = items.iter().map(Cfg::parse_nested); - match &*name.as_str() { + match &*name.to_string() { "all" => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)), "any" => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)), "not" => if sub_cfgs.len() == 1 { @@ -163,10 +163,10 @@ impl Cfg { Cfg::Any(ref sub_cfgs) | Cfg::All(ref sub_cfgs) => { sub_cfgs.first().map(Cfg::should_capitalize_first_letter).unwrap_or(false) }, - Cfg::Cfg(name, _) => match &*name.as_str() { + Cfg::Cfg(name, _) => name.with_str(|str| match str { "debug_assertions" | "target_endian" => true, _ => false, - }, + }), } } @@ -319,12 +319,12 @@ impl<'a> fmt::Display for Html<'a> { Cfg::False => fmt.write_str("nowhere"), Cfg::Cfg(name, value) => { - let n = &*name.as_str(); - let human_readable = match (n, value) { + let n = name.to_string(); + let human_readable = match (&*n, value) { ("unix", None) => "Unix", ("windows", None) => "Windows", ("debug_assertions", None) => "debug-assertions enabled", - ("target_os", Some(os)) => match &*os.as_str() { + ("target_os", Some(os)) => os.with_str(|str| match str { "android" => "Android", "bitrig" => "Bitrig", "dragonfly" => "DragonFly BSD", @@ -342,8 +342,8 @@ impl<'a> fmt::Display for Html<'a> { "solaris" => "Solaris", "windows" => "Windows", _ => "", - }, - ("target_arch", Some(arch)) => match &*arch.as_str() { + }), + ("target_arch", Some(arch)) => arch.with_str(|str| match str { "aarch64" => "AArch64", "arm" => "ARM", "asmjs" => "asm.js", @@ -358,22 +358,22 @@ impl<'a> fmt::Display for Html<'a> { "x86" => "x86", "x86_64" => "x86-64", _ => "", - }, - ("target_vendor", Some(vendor)) => match &*vendor.as_str() { + }), + ("target_vendor", Some(vendor)) => vendor.with_str(|str| match str { "apple" => "Apple", "pc" => "PC", "rumprun" => "Rumprun", "sun" => "Sun", _ => "" - }, - ("target_env", Some(env)) => match &*env.as_str() { + }), + ("target_env", Some(env)) => env.with_str(|str| match str { "gnu" => "GNU", "msvc" => "MSVC", "musl" => "musl", "newlib" => "Newlib", "uclibc" => "uClibc", _ => "", - }, + }), ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian), ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits), _ => "", @@ -381,9 +381,11 @@ impl<'a> fmt::Display for Html<'a> { if !human_readable.is_empty() { fmt.write_str(human_readable) } else if let Some(v) = value { - write!(fmt, "{}=\"{}\"", Escape(n), Escape(&*v.as_str())) + v.with_str(|str| { + write!(fmt, "{}=\"{}\"", Escape(&*n), Escape(str)) + }) } else { - write!(fmt, "{}", Escape(n)) + write!(fmt, "{}", Escape(&*n)) } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 10cb2e5f3fdaf..b76a7920f1dee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -234,7 +234,7 @@ impl Clean for CrateNum { for attr in attrs.lists("doc") { if let Some(v) = attr.value_str() { if attr.check_name("primitive") { - prim = PrimitiveType::from_str(&v.as_str()); + prim = v.with_str(|str| PrimitiveType::from_str(str)); if prim.is_some() { break; } @@ -846,8 +846,9 @@ impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did), - Some(did), false, vec![], empty); + let path = cx.tcx.item_name(did).with(|str| { + external_path(cx, str, Some(did), false, vec![], empty) + }); inline::record_extern_fqn(cx, did, TypeKind::Trait); TraitBound(PolyTrait { trait_: ResolvedPath { @@ -937,8 +938,9 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self impl<'tcx> Clean for ty::TraitRef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParamBound { inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(self.def_id), - Some(self.def_id), true, vec![], self.substs); + let path = cx.tcx.item_name(self.def_id).with(|str| { + external_path(cx, str, Some(self.def_id), true, vec![], self.substs) + }); debug!("ty::TraitRef\n subst: {:?}\n", self.substs); @@ -2233,8 +2235,9 @@ impl<'tcx> Clean for Ty<'tcx> { AdtKind::Enum => TypeKind::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, &cx.tcx.item_name(did), - None, false, vec![], substs); + let path = cx.tcx.item_name(did).with(|str| { + external_path(cx, str, None, false, vec![], substs) + }); ResolvedPath { path, typarams: None, @@ -2244,8 +2247,9 @@ impl<'tcx> Clean for Ty<'tcx> { } ty::TyForeign(did) => { inline::record_extern_fqn(cx, did, TypeKind::Foreign); - let path = external_path(cx, &cx.tcx.item_name(did), - None, false, vec![], Substs::empty()); + let path = cx.tcx.item_name(did).with(|str| { + external_path(cx, str, None, false, vec![], Substs::empty()) + }); ResolvedPath { path: path, typarams: None, @@ -2262,8 +2266,9 @@ impl<'tcx> Clean for Ty<'tcx> { reg.clean(cx).map(|b| typarams.push(RegionBound(b))); for did in obj.auto_traits() { let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did), - Some(did), false, vec![], empty); + let path = cx.tcx.item_name(did).with(|str| { + external_path(cx, str, Some(did), false, vec![], empty) + }); inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = TraitBound(PolyTrait { trait_: ResolvedPath { @@ -2285,8 +2290,9 @@ impl<'tcx> Clean for Ty<'tcx> { }); } - let path = external_path(cx, &cx.tcx.item_name(did), Some(did), - false, bindings, principal.0.substs); + let path = cx.tcx.item_name(did).with(|str| { + external_path(cx, str, Some(did), false, bindings, principal.0.substs) + }); ResolvedPath { path, typarams: Some(typarams), @@ -2693,7 +2699,7 @@ fn qpath_to_string(p: &hir::QPath) -> String { s.push_str("::"); } if seg.name != keywords::CrateRoot.name() { - s.push_str(&*seg.name.as_str()); + seg.name.with_str(|str| s.push_str(str)); } } s diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index ef01c3e6bdb0c..c3c7c8d4670dc 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -222,7 +222,7 @@ impl<'a> Classifier<'a> { -> io::Result<()> { let klass = match tas.tok { token::Shebang(s) => { - out.string(Escape(&s.as_str()), Class::None, Some(&tas))?; + s.with_str(|str| out.string(Escape(str), Class::None, Some(&tas)))?; return Ok(()); }, @@ -324,7 +324,7 @@ impl<'a> Classifier<'a> { // Keywords are also included in the identifier set. token::Ident(ident) => { - match &*ident.name.as_str() { + ident.name.with_str(|str| match str { "ref" | "mut" => Class::RefKeyWord, "self" |"Self" => Class::Self_, @@ -347,7 +347,7 @@ impl<'a> Classifier<'a> { Class::Ident } } - } + }) } token::Lifetime(..) => Class::Lifetime, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3be44f3095858..c3ed2fce3e7b7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -532,7 +532,7 @@ pub fn run(mut krate: clean::Crate, // going to emit HTML if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) { for attr in attrs.lists("doc") { - let name = attr.name().map(|s| s.as_str()); + let name = attr.name().map(|s| s.to_string()); match (name.as_ref().map(|s| &s[..]), attr.value_str()) { (Some("html_favicon_url"), Some(s)) => { scx.layout.favicon = s.to_string(); @@ -3025,7 +3025,7 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { for attr in &it.attrs.other_attrs { let name = attr.name().unwrap(); - if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) { + if name.with_str(|str| !ATTRIBUTE_WHITELIST.contains(&str)) { continue; } if let Some(s) = render_attribute(&attr.meta().unwrap()) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7ebacdec1f0b2..07e4f187d24d0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -521,7 +521,7 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. for attr in krate.module.as_ref().unwrap().attrs.lists("doc") { - let name = attr.name().map(|s| s.as_str()); + let name = attr.name().map(|s| s.to_string()); let name = name.as_ref().map(|s| &s[..]); if attr.is_word() { if name == Some("no_default_passes") { @@ -533,9 +533,9 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { Some("plugins") => &mut plugins, _ => continue, }; - for p in value.as_str().split_whitespace() { + value.with_str(|str| for p in str.split_whitespace() { sink.push(p.to_string()); - } + }); } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index cc72ff7d15d2b..ed172fa96e9df 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -370,7 +370,7 @@ impl Attribute { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( Symbol::intern("doc"), - Symbol::intern(&strip_doc_comment_decoration(&comment.as_str()))); + comment.with_str(|str| Symbol::intern(&strip_doc_comment_decoration(str)))); let mut attr = if self.style == ast::AttrStyle::Outer { mk_attr_outer(self.span, self.id, meta) } else { @@ -466,7 +466,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute } pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { - let style = doc_comment_style(&text.as_str()); + let style = text.with_str(|str| doc_comment_style(str)); let lit = respan(span, LitKind::Str(text, ast::StrStyle::Cooked)); Attribute { id, @@ -600,7 +600,7 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) // The unwraps below may look dangerous, but we've already asserted // that they won't fail with the loop above. - match &*cfg.name.as_str() { + cfg.name.with_str(|str| match str { "any" => mis.iter().any(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), @@ -619,7 +619,7 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p); false } - } + }) }, ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => { eval(cfg) @@ -712,7 +712,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, )+ for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name().as_str() { + match &*mi.name.with_str(|str| str.to_string()) { $( stringify!($name) => if !get(mi, &mut $name) { continue 'outer }, @@ -731,7 +731,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } } - match &*meta.name.as_str() { + match &*meta.name.with_str(|str| str.to_string()) { "rustc_deprecated" => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, @@ -786,7 +786,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut issue = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name().as_str() { + match &*mi.name().with_str(|str| str.to_string()) { "feature" => if !get(mi, &mut feature) { continue 'outer }, "reason" => if !get(mi, &mut reason) { continue 'outer }, "issue" => if !get(mi, &mut issue) { continue 'outer }, @@ -808,7 +808,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, level: Unstable { reason, issue: { - if let Ok(issue) = issue.as_str().parse() { + if let Ok(issue) = issue.with_str(|str| str.parse()) { issue } else { span_err!(diagnostic, attr.span(), E0545, @@ -842,7 +842,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut since = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name().as_str() { + match &*mi.name().with_str(|str| str.to_string()) { "feature" => if !get(mi, &mut feature) { continue 'outer }, "since" => if !get(mi, &mut since) { continue 'outer }, _ => { @@ -950,7 +950,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, let mut note = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name().as_str() { + match &*mi.name().with_str(|str| str.to_string()) { "since" => if !get(mi, &mut since) { continue 'outer }, "note" => if !get(mi, &mut note) { continue 'outer }, _ => { @@ -1006,19 +1006,18 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec let mut recognised = false; if let Some(mi) = item.word() { - let word = &*mi.name().as_str(); - let hint = match word { + let hint = mi.name().with_str(|str| match str { // Can't use "extern" because it's not a lexical identifier. "C" => Some(ReprExtern), "packed" => Some(ReprPacked), "simd" => Some(ReprSimd), - _ => match int_type_of_word(word) { + _ => match mi.name().with_str(|str| int_type_of_word(str)) { Some(ity) => Some(ReprInt(ity)), None => { None } } - }; + }); if let Some(h) = hint { recognised = true; @@ -1230,9 +1229,9 @@ impl LitKind { match *self { LitKind::Str(string, ast::StrStyle::Cooked) => { let mut escaped = String::new(); - for ch in string.as_str().chars() { + string.with_str(|str| for ch in str.chars() { escaped.extend(ch.escape_unicode()); - } + }); Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None) } LitKind::Str(string, ast::StrStyle::Raw(n)) => { diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 5224f52c49629..cf4c3ecef160a 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -109,8 +109,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, // Check that the description starts and ends with a newline and doesn't // overflow the maximum line width. - description.map(|raw_msg| { - let msg = raw_msg.as_str(); + description.map(|raw_msg| raw_msg.with_str(|msg| { if !msg.starts_with("\n") || !msg.ends_with("\n") { ecx.span_err(span, &format!( "description for error code {} doesn't start and end with a newline", @@ -129,7 +128,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, code, MAX_DESCRIPTION_WIDTH )); } - }); + })); // Add the error to the map. with_registered_diagnostics(|diagnostics| { let info = ErrorInfo { @@ -174,10 +173,10 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, // Output error metadata to `tmp/extended-errors//.json` if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") { with_registered_diagnostics(|diagnostics| { - if let Err(e) = output_metadata(ecx, - &target_triple, - &crate_name.name.as_str(), - diagnostics) { + if let Err(e) = crate_name.name.with_str(|crate_name| output_metadata(ecx, + &target_triple, + crate_name, + diagnostics)) { ecx.span_bug(span, &format!( "error writing metadata for triple `{}` and crate `{}`, error: {}, \ cause: {:?}", diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 81baa0c3954ca..0fb66ccc3e1b5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -167,7 +167,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { if segment.identifier.name != keywords::CrateRoot.name() && segment.identifier.name != keywords::DollarCrate.name() { - path_str.push_str(&segment.identifier.name.as_str()) + segment.identifier.name.with_str(|str| path_str.push_str(str)) } } @@ -978,9 +978,9 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; - module.directory.push(&*path.as_str()); + path.with_str(|str| module.directory.push(str)); } else { - module.directory.push(&*item.ident.name.as_str()); + item.ident.name.with_str(|str| module.directory.push(str)); } } else { let path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 2167b64e6103d..df320ccb8447e 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -392,7 +392,7 @@ fn inner_parse_loop(sess: &ParseSess, TokenTree::MetaVarDecl(_, _, id) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. - if may_begin_with(&*id.name.as_str(), token) { + if id.name.with_str(|str| may_begin_with(str, token)) { bb_items.push(item); } } @@ -482,7 +482,9 @@ pub fn parse(sess: &ParseSess, if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; item.push_match(match_cur, - MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str())))); + MatchedNonterminal(Rc::new(ident.name.with_str(|str| parse_nt(&mut parser, + span, + str))))); item.idx += 1; item.match_cur += 1; } else { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 5e58f003c2be7..575ec9401552a 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -713,7 +713,7 @@ fn check_matcher_core(sess: &ParseSess, 'each_last: for token in &last.tokens { if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token { for next_token in &suffix_first.tokens { - match is_in_follow(next_token, &frag_spec.name.as_str()) { + match frag_spec.name.with_str(|str| is_in_follow(next_token, str)) { Err((msg, help)) => { sess.span_diagnostic.struct_span_err(next_token.span(), &msg) .help(help).emit(); @@ -751,7 +751,7 @@ fn check_matcher_core(sess: &ParseSess, fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool { if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { - frag_can_be_followed_by_any(&frag_spec.name.as_str()) + frag_spec.name.with_str(|str| frag_can_be_followed_by_any(str)) } else { // (Non NT's can always be followed by anthing in matchers.) true @@ -870,10 +870,12 @@ fn has_legal_fragment_specifier(sess: &ParseSess, tok: "ed::TokenTree) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { - let frag_name = frag_spec.name.as_str(); let frag_span = tok.span(); - if !is_legal_fragment_specifier(sess, features, attrs, &frag_name, frag_span) { - return Err(frag_name.to_string()); + let legal = frag_spec.name.with_str(|frag_name| { + is_legal_fragment_specifier(sess, features, attrs, frag_name, frag_span) + }); + if !legal { + return Err(frag_spec.name.with_str(|str| str.to_string())); } } Ok(()) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7ae360678cd50..fa463ec94e36f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1077,12 +1077,12 @@ impl<'a> Context<'a> { return; } } - if name.starts_with("rustc_") { + if name.with(|str| str.starts_with("rustc_")) { gate_feature!(self, rustc_attrs, attr.span, "unless otherwise specified, attributes \ with the prefix `rustc_` \ are reserved for internal compiler diagnostics"); - } else if name.starts_with("derive_") { + } else if name.with(|str| str.starts_with("derive_")) { gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); } else if !attr::is_known(attr) { // Only run the custom attribute lint during regular @@ -1448,7 +1448,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_name(&mut self, sp: Span, name: ast::Name) { - if !name.as_str().is_ascii() { + if !name.with_str(|str| str.is_ascii()) { gate_feature_post!(&self, non_ascii_idents, self.context.parse_sess.codemap().def_span(sp), @@ -1579,7 +1579,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ForeignItemKind::Static(..) => { let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name"); let links_to_llvm = match link_name { - Some(val) => val.as_str().starts_with("llvm."), + Some(val) => val.with_str(|str| str.starts_with("llvm.")), _ => false }; if links_to_llvm { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index a38ceba2f45a9..37ed4e71574d5 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -402,27 +402,27 @@ pub fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Hand use ast::LitKind; match lit { - token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))), - token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))), + token::Byte(i) => (true, Some(LitKind::Byte(i.with_str(|str| byte_lit(str).0)))), + token::Char(i) => (true, Some(LitKind::Char(i.with_str(|str| char_lit(str, diag).0)))), // There are some valid suffixes for integer and float literals, // so all the handling is done internally. - token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)), - token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)), + token::Integer(s) => (false, integer_lit(s, suf, diag)), + token::Float(s) => (false, float_lit(s, suf, diag)), token::Str_(s) => { - let s = Symbol::intern(&str_lit(&s.as_str(), diag)); + let s = Symbol::intern(&s.with_str(|str| str_lit(str, diag))); (true, Some(LitKind::Str(s, ast::StrStyle::Cooked))) } token::StrRaw(s, n) => { - let s = Symbol::intern(&raw_str_lit(&s.as_str())); + let s = Symbol::intern(&s.with_str(|str| raw_str_lit(str))); (true, Some(LitKind::Str(s, ast::StrStyle::Raw(n)))) } token::ByteStr(i) => { - (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str())))) + (true, Some(LitKind::ByteStr(i.with_str(|str| byte_str_lit(str))))) } token::ByteStrRaw(i, _) => { - (true, Some(LitKind::ByteStr(Rc::new(i.to_string().into_bytes())))) + (true, Some(LitKind::ByteStr(Rc::new(i.with_str(|str| str.to_string()).into_bytes())))) } } } @@ -435,7 +435,7 @@ fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, None => return Some(ast::LitKind::FloatUnsuffixed(data)), }; - Some(match &*suffix.as_str() { + Some(match &*suffix.with_str(|str| str.to_string()) { "f32" => ast::LitKind::Float(data, ast::FloatTy::F32), "f64" => ast::LitKind::Float(data, ast::FloatTy::F64), suf => { @@ -456,11 +456,11 @@ fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, } }) } -pub fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) +pub fn float_lit(s: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) -> Option { debug!("float_lit: {:?}, {:?}", s, suffix); // FIXME #2252: bounds checking float literals is deferred until trans - let s = s.chars().filter(|&c| c != '_').collect::(); + let s = s.with_str(|str| str.chars().filter(|&c| c != '_').collect::()); filtered_float_lit(Symbol::intern(&s), suffix, diag) } @@ -556,11 +556,11 @@ pub fn byte_str_lit(lit: &str) -> Rc> { Rc::new(res) } -pub fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) +pub fn integer_lit(s: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) -> Option { // s can only be ascii, byte indexing is fine - let s2 = s.chars().filter(|&c| c != '_').collect::(); + let s2 = s.with_str(|str| str.chars().filter(|&c| c != '_').collect::()); let mut s = &s2[..]; debug!("integer_lit: {}, {:?}", s, suffix); @@ -580,7 +580,7 @@ pub fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler // 1f64 and 2f32 etc. are valid float literals. if let Some(suf) = suffix { - if looks_like_width_suffix(&['f'], &suf.as_str()) { + if suf.with_str(|str| looks_like_width_suffix(&['f'], str)) { let err = match base { 16 => Some("hexadecimal float literal is not supported"), 8 => Some("octal float literal is not supported"), @@ -599,10 +599,10 @@ pub fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler } if let Some(suf) = suffix { - if suf.as_str().is_empty() { + if suf.with_str(|str| str.is_empty()) { err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some")); } - ty = match &*suf.as_str() { + ty = match &*suf.with_str(|str| str.to_string()) { "isize" => ast::LitIntType::Signed(ast::IntTy::Is), "i8" => ast::LitIntType::Signed(ast::IntTy::I8), "i16" => ast::LitIntType::Signed(ast::IntTy::I16), @@ -635,7 +635,7 @@ pub fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler ty } - } + }; } debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a4aad81f5f5af..f412c380b3d2b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -342,7 +342,7 @@ impl TokenCursor { tok => return tok, }; - let stripped = strip_doc_comment_decoration(&name.as_str()); + let stripped = name.with_str(|str| strip_doc_comment_decoration(str)); // Searches for the occurrences of `"#*` and returns the minimum number of `#`s // required to wrap the text. @@ -368,7 +368,7 @@ impl TokenCursor { self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(sp, &Delimited { delim: token::NoDelim, - tts: if doc_comment_style(&name.as_str()) == AttrStyle::Inner { + tts: if name.with_str(|str| doc_comment_style(str)) == AttrStyle::Inner { [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] .iter().cloned().collect::().into() } else { @@ -895,8 +895,7 @@ impl<'a> Parser<'a> { match suffix { None => {/* everything ok */} Some(suf) => { - let text = suf.as_str(); - if text.is_empty() { + if suf.with_str(|str| str.is_empty()) { self.span_bug(sp, "found empty literal suffix in Some") } self.span_err(sp, &format!("{} with a suffix is invalid", kind)); @@ -2602,7 +2601,7 @@ impl<'a> Parser<'a> { hi = self.span; self.bump(); - let index = n.as_str().parse::().ok(); + let index = n.with_str(|str| str.parse::().ok()); match index { Some(n) => { let id = respan(dot_span.to(hi), n); @@ -2617,12 +2616,11 @@ impl<'a> Parser<'a> { } token::Literal(token::Float(n), _suf) => { self.bump(); - let fstr = n.as_str(); let mut err = self.diagnostic().struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n)); err.span_label(self.prev_span, "unexpected token"); - if fstr.chars().all(|x| "0123456789.".contains(x)) { - let float = match fstr.parse::().ok() { + if n.with_str(|str| str.chars().all(|x| "0123456789.".contains(x))) { + let float = match n.with_str(|str| str.parse::().ok()) { Some(f) => f, None => continue, }; @@ -2634,7 +2632,7 @@ impl<'a> Parser<'a> { s.print_usize(float.trunc() as usize)?; s.pclose()?; s.s.word(".")?; - s.s.word(fstr.splitn(2, ".").last().unwrap()) + n.with_str(|str| s.s.word(str.splitn(2, ".").last().unwrap())) }); err.span_suggestion( lo.to(self.prev_span), @@ -5783,15 +5781,17 @@ impl<'a> Parser<'a> { fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") { - self.directory.path.push(&path.as_str()); + path.with_str(|str| self.directory.path.push(str)); self.directory.ownership = DirectoryOwnership::Owned { relative: None }; } else { - self.directory.path.push(&id.name.as_str()); + id.name.with_str(|str| self.directory.path.push(str)); } } pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option { - attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str())) + attr::first_attr_value_str_by_name(attrs, "path").map(|d| { + d.with_str(|str| dir_path.join(str)) + }) } /// Returns either a path to a module, or . @@ -6180,7 +6180,7 @@ impl<'a> Parser<'a> { let sp = self.span; self.expect_no_suffix(sp, "ABI spec", suf); self.bump(); - match abi::lookup(&s.as_str()) { + match s.with_str(|str| abi::lookup(str)) { Some(abi) => Ok(Some(abi)), None => { let prev_span = self.prev_span; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8f619e8af765a..90fe3b66fd8de 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -243,7 +243,7 @@ pub fn token_to_string(tok: &Token) -> String { }; if let Some(s) = suf { - out.push_str(&s.as_str()) + s.with_str(|str| out.push_str(str)) } out @@ -601,7 +601,7 @@ pub trait PrintState<'a> { return self.writer().word(<rl.lit); } match lit.node { - ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), + ast::LitKind::Str(st, style) => st.with_str(|str| self.print_string(str, style)), ast::LitKind::Byte(byte) => { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); @@ -630,7 +630,7 @@ pub trait PrintState<'a> { ast::LitKind::Float(ref f, t) => { self.writer().word(&format!("{}{}", &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()), + ast::LitKind::FloatUnsuffixed(ref f) => f.with_str(|str| self.writer().word(str)), ast::LitKind::Bool(val) => { if val { self.writer().word("true") } else { self.writer().word("false") } } @@ -718,7 +718,7 @@ pub trait PrintState<'a> { } self.maybe_print_comment(attr.span.lo())?; if attr.is_sugared_doc { - self.writer().word(&attr.value_str().unwrap().as_str())?; + attr.value_str().unwrap().with_str(|str| self.writer().word(str))?; self.writer().hardbreak() } else { match attr.style { @@ -734,7 +734,7 @@ pub trait PrintState<'a> { } if segment.identifier.name != keywords::CrateRoot.name() && segment.identifier.name != keywords::DollarCrate.name() { - self.writer().word(&segment.identifier.name.as_str())?; + segment.identifier.name.with_str(|str| self.writer().word(str))?; } else if segment.identifier.name == keywords::DollarCrate.name() { self.print_dollar_crate(segment.identifier.ctxt)?; } @@ -761,15 +761,15 @@ pub trait PrintState<'a> { self.ibox(INDENT_UNIT)?; match item.node { ast::MetaItemKind::Word => { - self.writer().word(&item.name.as_str())?; + item.name.with_str(|str| self.writer().word(str))?; } ast::MetaItemKind::NameValue(ref value) => { - self.word_space(&item.name.as_str())?; + item.name.with_str(|str| self.word_space(str))?; self.word_space("=")?; self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - self.writer().word(&item.name.as_str())?; + item.name.with_str(|str| self.writer().word(str))?; self.popen()?; self.commasep(Consistent, &items[..], @@ -1176,12 +1176,13 @@ impl<'a> State<'a> { ast::ItemKind::ExternCrate(ref optional_path) => { self.head(&visibility_qualified(&item.vis, "extern crate"))?; if let Some(p) = *optional_path { - let val = p.as_str(); - if val.contains('-') { - self.print_string(&val, ast::StrStyle::Cooked)?; - } else { - self.print_name(p)?; - } + p.with_str(|val| { + if val.contains('-') { + self.print_string(&val, ast::StrStyle::Cooked) + } else { + self.print_name(p) + } + })?; self.s.space()?; self.s.word("as")?; self.s.space()?; @@ -1258,7 +1259,7 @@ impl<'a> State<'a> { } ast::ItemKind::GlobalAsm(ref ga) => { self.head(&visibility_qualified(&item.vis, "global_asm!"))?; - self.s.word(&ga.asm.as_str())?; + ga.asm.with_str(|str| self.s.word(str))?; self.end()?; } ast::ItemKind::Ty(ref ty, ref generics) => { @@ -2278,19 +2279,20 @@ impl<'a> State<'a> { ast::ExprKind::InlineAsm(ref a) => { self.s.word("asm!")?; self.popen()?; - self.print_string(&a.asm.as_str(), a.asm_str_style)?; + a.asm.with_str(|str| self.print_string(str, a.asm_str_style))?; self.word_space(":")?; self.commasep(Inconsistent, &a.outputs, |s, out| { - let constraint = out.constraint.as_str(); - let mut ch = constraint.chars(); - match ch.next() { - Some('=') if out.is_rw => { - s.print_string(&format!("+{}", ch.as_str()), - ast::StrStyle::Cooked)? + out.constraint.with_str(|constraint| { + let mut ch = constraint.chars(); + match ch.next() { + Some('=') if out.is_rw => { + s.print_string(&format!("+{}", ch.as_str()), + ast::StrStyle::Cooked) + } + _ => s.print_string(&constraint, ast::StrStyle::Cooked) } - _ => s.print_string(&constraint, ast::StrStyle::Cooked)? - } + })?; s.popen()?; s.print_expr(&out.expr)?; s.pclose()?; @@ -2300,7 +2302,7 @@ impl<'a> State<'a> { self.word_space(":")?; self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { - s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; + co.with_str(|str| s.print_string(str, ast::StrStyle::Cooked))?; s.popen()?; s.print_expr(o)?; s.pclose()?; @@ -2311,7 +2313,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &a.clobbers, |s, co| { - s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; + co.with_str(|str| s.print_string(str, ast::StrStyle::Cooked))?; Ok(()) })?; @@ -2379,7 +2381,7 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - self.s.word(&ident.name.as_str())?; + ident.name.with_str(|str| self.s.word(str))?; self.ann.post(self, NodeIdent(&ident)) } @@ -2388,7 +2390,7 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - self.s.word(&name.as_str())?; + name.with_str(|str| self.s.word(str))?; self.ann.post(self, NodeName(&name)) } diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index e429791f2bdd4..b92e55e15623d 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -55,7 +55,7 @@ pub fn find_best_match_for_name<'a, T>(iter_names: T, let (case_insensitive_match, levenstein_match) = iter_names .filter_map(|&name| { - let dist = lev_distance(lookup, &name.as_str()); + let dist = name.with_str(|name| lev_distance(lookup, name)); if dist <= max_dist { Some((name, dist)) } else { @@ -66,7 +66,7 @@ pub fn find_best_match_for_name<'a, T>(iter_names: T, // (case_insensitive_match, (levenstein_match, levenstein_distance)) .fold((None, None), |result, (candidate, dist)| { ( - if candidate.as_str().to_uppercase() == lookup.to_uppercase() { + if candidate.with_str(|str| str.to_uppercase()) == lookup.to_uppercase() { Some(candidate) } else { result.0 diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 3742fb8c804d7..6617552d9ac5f 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -134,26 +134,27 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, // It's the opposite of '=&' which means that the memory // cannot be shared with any other operand (usually when // a register is clobbered early.) - let constraint_str = constraint.as_str(); - let mut ch = constraint_str.chars(); - let output = match ch.next() { - Some('=') => None, - Some('+') => { - Some(Symbol::intern(&format!("={}", ch.as_str()))) - } - _ => { - cx.span_err(span, "output operand constraint lacks '=' or '+'"); - None - } - }; + constraint.with_str(|constraint_str| { + let mut ch = constraint_str.chars(); + let output = match ch.next() { + Some('=') => None, + Some('+') => { + Some(Symbol::intern(&format!("={}", ch.as_str()))) + } + _ => { + cx.span_err(span, "output operand constraint lacks '=' or '+'"); + None + } + }; - let is_rw = output.is_some(); - let is_indirect = constraint_str.contains("*"); - outputs.push(ast::InlineAsmOutput { - constraint: output.unwrap_or(constraint), - expr: out, - is_rw, - is_indirect, + let is_rw = output.is_some(); + let is_indirect = constraint_str.contains("*"); + outputs.push(ast::InlineAsmOutput { + constraint: output.unwrap_or(constraint), + expr: out, + is_rw, + is_indirect, + }); }); } } @@ -166,9 +167,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, let (constraint, _str_style) = panictry!(p.parse_str()); - if constraint.as_str().starts_with("=") { + if constraint.with_str(|str| str.starts_with("=")) { cx.span_err(p.prev_span, "input operand constraint contains '='"); - } else if constraint.as_str().starts_with("+") { + } else if constraint.with_str(|str| str.starts_with("+")) { cx.span_err(p.prev_span, "input operand constraint contains '+'"); } @@ -190,7 +191,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.prev_span, "expected a clobber, found an option"); - } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") { + } else if s.with_str(|str| str.starts_with("{") || str.ends_with("}")) { cx.span_err(p.prev_span, "clobber should not be surrounded by braces"); } diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index c79e7867c5f5e..f876fbefe0256 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -33,7 +33,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) | ast::LitKind::FloatUnsuffixed(ref s) => { - accumulator.push_str(&s.as_str()); + s.with_str(|str| accumulator.push_str(str)); } ast::LitKind::Char(c) => { accumulator.push(c); diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 8d0104e512bfb..cef5351582fc0 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -44,7 +44,9 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, } } else { match *e { - TokenTree::Token(_, token::Ident(ident)) => res_str.push_str(&ident.name.as_str()), + TokenTree::Token(_, token::Ident(ident)) => { + ident.name.with_str(|str| res_str.push_str(str)) + } _ => { cx.span_err(sp, "concat_idents! requires ident args."); return DummyResult::expr(sp); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 29f5196c9bd6f..7d0ff7ae10f8e 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -467,10 +467,10 @@ impl<'a> TraitDef<'a> { attrs.extend(item.attrs .iter() .filter(|a| { - a.name().is_some() && match &*a.name().unwrap().as_str() { + a.name().is_some() && a.name().unwrap().with_str(|str| match str { "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true, _ => false, - } + }) }) .cloned()); push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 8159893e784e4..211920f6f0a56 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -55,10 +55,10 @@ pub mod generic; macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { pub fn is_builtin_trait(name: ast::Name) -> bool { - match &*name.as_str() { + name.with_str(|str| match str { $( $name )|+ => true, _ => false, - } + }) } pub fn register_builtin_derives(resolver: &mut Resolver) { @@ -125,7 +125,7 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { for param in params.iter() { if let ast::GenericParam::Type(ref ty) = *param{ - typaram.push_str(&ty.ident.name.as_str()); + ty.ident.name.with_str(|str| typaram.push_str(str)); } } } diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index fcad065be52bc..67fd510c67fee 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -87,9 +87,9 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, return DummyResult::expr(sp); } - let e = match env::var(&*var.as_str()) { + let e = match var.with_str(|str| env::var(str)) { Err(_) => { - cx.span_err(sp, &msg.as_str()); + msg.with_str(|str| cx.span_err(sp, str)); cx.expr_usize(sp, 0) } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index ad5bd39a45341..278aa481000ea 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -166,11 +166,11 @@ fn parse_args(ecx: &mut ExtCtxt, return None; } }; - let name: &str = &ident.name.as_str(); + let name = ident.name.to_string(); panictry!(p.expect(&token::Eq)); let e = panictry!(p.parse_expr()); - if let Some(prev) = names.get(name) { + if let Some(prev) = names.get(&name) { ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name)) .span_note(args[*prev].span, "previously here") .emit(); @@ -728,8 +728,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, invalid_refs: Vec::new(), }; - let fmt_str = &*fmt.node.0.as_str(); - let mut parser = parse::Parser::new(fmt_str); + let fmt_str = fmt.node.0.to_string(); + let mut parser = parse::Parser::new(&fmt_str); let mut pieces = vec![]; loop { @@ -842,7 +842,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, ($kind:ident) => {{ let mut show_doc_note = false; - for sub in foreign::$kind::iter_subs(fmt_str) { + for sub in foreign::$kind::iter_subs(&fmt_str) { let trn = match sub.translate() { Some(trn) => trn, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index aafdd696b747d..0428bc4bc9e69 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -18,6 +18,8 @@ use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::cell::RefCell; use std::collections::HashMap; use std::fmt; +use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; +use std::hash::{Hash, Hasher}; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Ident { @@ -36,7 +38,7 @@ impl Ident { } pub fn without_first_quote(&self) -> Ident { - Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt } + Ident { name: Symbol::from(self.name.to_string().trim_left_matches('\'')), ctxt: self.ctxt } } pub fn modern(self) -> Ident { @@ -59,10 +61,10 @@ impl fmt::Display for Ident { impl Encodable for Ident { fn encode(&self, s: &mut S) -> Result<(), S::Error> { if self.ctxt.modern() == SyntaxContext::empty() { - s.emit_str(&self.name.as_str()) + self.name.with_str(|str| s.emit_str(str)) } else { // FIXME(jseyfried) intercrate hygiene let mut string = "#".to_owned(); - string.push_str(&self.name.as_str()); + self.name.with_str(|str| string.push_str(str)); s.emit_str(&string) } } @@ -106,12 +108,16 @@ impl Symbol { with_interner(|interner| interner.gensymed(self)) } + pub fn with_str R, R>(self, f: F) -> R { + self.as_str().with(f) + } + pub fn as_str(self) -> InternedString { - with_interner(|interner| unsafe { - InternedString { - string: ::std::mem::transmute::<&str, &str>(interner.get(self)) - } - }) + InternedString { + // Return an interned (non-gensymed) string so we can compare symbols + // in the PartialEq implementation of InternedString + symbol: self.interned(), + } } pub fn as_u32(self) -> u32 { @@ -144,7 +150,7 @@ impl fmt::Display for Symbol { impl Encodable for Symbol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) + Encodable::encode(&self.as_str(), s) } } @@ -210,7 +216,7 @@ impl Interner { Symbol(!0 - self.gensyms.len() as u32 + 1) } - fn is_gensymed(&mut self, symbol: Symbol) -> bool { + fn is_gensymed(&self, symbol: Symbol) -> bool { symbol.0 as usize >= self.strings.len() } @@ -330,80 +336,114 @@ declare_keywords! { (60, Union, "union") } +thread_local!(static INTERNER: RefCell = { + RefCell::new(Interner::fresh()) +}); + // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. fn with_interner T>(f: F) -> T { - thread_local!(static INTERNER: RefCell = { - RefCell::new(Interner::fresh()) - }); INTERNER.with(|interner| f(&mut *interner.borrow_mut())) } -/// Represents a string stored in the thread-local interner. Because the -/// interner lives for the life of the thread, this can be safely treated as an -/// immortal string, as long as it never crosses between threads. -/// -/// FIXME(pcwalton): You must be careful about what you do in the destructors -/// of objects stored in TLS, because they may run after the interner is -/// destroyed. In particular, they must not access string contents. This can -/// be fixed in the future by just leaking all strings until thread death -/// somehow. -#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] +/// Represents a string stored in the thread-local interner. +/// This accesses the thread-local interner in order to get to the string. +#[derive(Clone, Copy, Eq)] pub struct InternedString { - string: &'static str, + symbol: Symbol, +} + +impl InternedString { + pub fn with R, R>(self, f: F) -> R { + INTERNER.with(|interner| { + let str = interner.borrow_mut().get(self.symbol) as *const str; + // This is safe because the interner never frees strings, it just adds new ones + // We can access it because we know the interner is still alive + unsafe { f(&*str) } + }) + } + + pub fn as_symbol(self) -> Symbol { + self.symbol + } +} + +impl Hash for InternedString { + fn hash(&self, state: &mut H) { + self.with(|str| str.hash(state)) + } } -impl ::std::convert::AsRef for InternedString where str: ::std::convert::AsRef { - fn as_ref(&self) -> &U { - self.string.as_ref() +impl PartialOrd for InternedString { + fn partial_cmp(&self, other: &InternedString) -> Option { + if self.symbol == other.symbol { + return Some(Ordering::Equal); + } + self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str))) } } -impl> ::std::cmp::PartialEq for InternedString { +impl Ord for InternedString { + fn cmp(&self, other: &InternedString) -> Ordering { + if self.symbol == other.symbol { + return Ordering::Equal; + } + self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str))) + } +} + +impl> PartialEq for InternedString { fn eq(&self, other: &T) -> bool { - self.string == other.deref() + self.with(|string| string == other.deref()) } } -impl ::std::cmp::PartialEq for str { +impl PartialEq for InternedString { fn eq(&self, other: &InternedString) -> bool { - self == other.string + self.symbol == other.symbol } } -impl<'a> ::std::cmp::PartialEq for &'a str { +impl PartialEq for str { fn eq(&self, other: &InternedString) -> bool { - *self == other.string + other.with(|string| self == string) } } -impl ::std::cmp::PartialEq for String { +impl<'a> PartialEq for &'a str { fn eq(&self, other: &InternedString) -> bool { - self == other.string + other.with(|string| *self == string) } } -impl<'a> ::std::cmp::PartialEq for &'a String { +impl PartialEq for String { fn eq(&self, other: &InternedString) -> bool { - *self == other.string + other.with(|string| self == string) } } -impl !Send for InternedString { } +impl<'a> PartialEq for &'a String { + fn eq(&self, other: &InternedString) -> bool { + other.with(|string| *self == string) + } +} -impl ::std::ops::Deref for InternedString { - type Target = str; - fn deref(&self) -> &str { self.string } +impl ::std::convert::From for String { + fn from(val: InternedString) -> String { + val.as_symbol().to_string() + } } +impl !Send for InternedString { } + impl fmt::Debug for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.string, f) + self.with(|str| fmt::Debug::fmt(&str, f)) } } impl fmt::Display for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self.string, f) + self.with(|str| fmt::Display::fmt(&str, f)) } } @@ -415,7 +455,7 @@ impl Decodable for InternedString { impl Encodable for InternedString { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self.string) + self.with(|string| s.emit_str(string)) } } diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs index a0c72243d4821..687afcf291183 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -37,11 +37,11 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match &*it.name.as_str() { + it.name.with_str(|str| match str { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), _ => {} - } + }) } } diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs index a1efbb88a4d2e..2a81346e4154f 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs @@ -85,11 +85,11 @@ fn assert_invoc(slice: &mut &[TokenTree]) { fn assert_foo(slice: &mut &[TokenTree]) { match slice[0].kind { - TokenNode::Term(ref name) => assert_eq!(name.as_str(), "fn"), + TokenNode::Term(ref name) => name.with_str(|str| assert_eq!(str, "fn")), _ => panic!("expected fn"), } match slice[1].kind { - TokenNode::Term(ref name) => assert_eq!(name.as_str(), "foo"), + TokenNode::Term(ref name) => name.with_str(|str| assert_eq!(str, "foo")), _ => panic!("expected foo"), } match slice[2].kind { diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs index e2c68a626f91e..7de57a1c0b39b 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs @@ -33,7 +33,7 @@ pub fn cond(input: TokenStream) -> TokenStream { panic!("Invalid macro usage in cond: {}", cond); } let is_else = match test.kind { - TokenNode::Term(word) => word.as_str() == "else", + TokenNode::Term(word) => word.with_str(|str| str == "else"), _ => false, }; conds.push(if is_else || input.peek().is_none() { diff --git a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs index a0c72243d4821..687afcf291183 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -37,11 +37,11 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match &*it.name.as_str() { + it.name.with_str(|str| match str { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), _ => {} - } + }) } }