Skip to content

Commit 164f010

Browse files
Add safe_suggestion attribute
1 parent 601bbf2 commit 164f010

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#![cfg_attr(test, allow(deprecated))] // rand
3030
#![cfg_attr(not(stage0), deny(warnings))]
31+
#![cfg_attr(not(stage0), feature(safe_suggestion))]
3132

3233
#![feature(alloc)]
3334
#![feature(allow_internal_unstable)]

src/libcollections/string.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,7 @@ impl String {
12311231
/// assert_eq!(a.len(), 3);
12321232
/// ```
12331233
#[inline]
1234+
#[cfg_attr(not(stage0), safe_suggestion)]
12341235
#[stable(feature = "rust1", since = "1.0.0")]
12351236
pub fn len(&self) -> usize {
12361237
self.vec.len()

src/librustc/infer/error_reporting.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -587,19 +587,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
587587
// look for expected with found id
588588
self.tcx.populate_inherent_implementations_for_type_if_necessary(found);
589589
if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&found) {
590-
let mut methods = Vec::new();
590+
let mut methods: Vec<(Option<ast::Attribute>, DefId, ImplOrTraitItem<'tcx>)> = Vec::new();
591591
for impl_ in impl_infos {
592592
methods.append(&mut self.tcx
593593
.impl_or_trait_items(*impl_)
594594
.iter()
595-
.map(|&did| self.tcx.impl_or_trait_item(did))
596-
.filter(|x| {
595+
.map(|&did| (None, did, self.tcx.impl_or_trait_item(did)))
596+
.filter(|&(_, _, ref x)| {
597597
self.matches_return_type(x, &expected_ty)
598598
})
599599
.collect());
600600
}
601-
for method in methods {
602-
println!("==> {:?}", method.name());
601+
let safe_suggestions: Vec<_> = methods.iter()
602+
.map(|&(_, ref id, ref x)| (self.find_attr(*id, "safe_suggestion"), id, x))
603+
.filter(|&(ref res, _, _)| res.is_some())
604+
.collect();
605+
if safe_suggestions.len() > 0 {
606+
for (_, _, method) in safe_suggestions {
607+
println!("safe ==> {:?}", method.name());
608+
}
609+
} else {
610+
for &(_, _, ref method) in methods.iter() {
611+
println!("not safe ==> {:?}", method.name());
612+
}
603613
}
604614
}
605615
}
@@ -615,6 +625,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
615625
self.tcx.note_and_explain_type_err(diag, terr, span);
616626
}
617627

628+
fn find_attr(&self, def_id: DefId, attr_name: &str) -> Option<ast::Attribute> {
629+
for item in self.tcx.get_attrs(def_id).iter() {
630+
if item.check_name(attr_name) {
631+
return Some(item.clone());
632+
}
633+
}
634+
None
635+
}
636+
618637
pub fn report_and_explain_type_error(&self,
619638
trace: TypeTrace<'tcx>,
620639
terr: &TypeError<'tcx>)

src/libsyntax/feature_gate.rs

+9
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ declare_features! (
304304
// Allows using `Self` and associated types in struct expressions and patterns.
305305
(active, more_struct_aliases, "1.14.0", Some(37544)),
306306

307+
307308
// Allows #[link(..., cfg(..))]
308309
(active, link_cfg, "1.14.0", Some(37406)),
309310

@@ -314,6 +315,9 @@ declare_features! (
314315

315316
// Allows #[target_feature(...)]
316317
(active, target_feature, "1.15.0", None),
318+
319+
// Allow safe suggestions for potential type conversions.
320+
(active, safe_suggestion, "1.0.0", Some(37384)),
317321
);
318322

319323
declare_features! (
@@ -648,6 +652,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
648652
"internal implementation detail",
649653
cfg_fn!(rustc_attrs))),
650654

655+
("safe_suggestion", Whitelisted, Gated("safe_suggestion",
656+
"the `#[safe_suggestion]` attribute \
657+
is an experimental feature",
658+
cfg_fn!(safe_suggestion))),
659+
651660
// FIXME: #14408 whitelist docs since rustdoc looks at them
652661
("doc", Whitelisted, Ungated),
653662

0 commit comments

Comments
 (0)