Skip to content

Commit 05796e2

Browse files
Add safe_suggestion attribute
1 parent b4964f7 commit 05796e2

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

src/libcollections/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,7 @@ impl String {
12341234
/// assert_eq!(a.len(), 3);
12351235
/// ```
12361236
#[inline]
1237+
#[cfg_attr(not(stage0), safe_suggestion)]
12371238
#[stable(feature = "rust1", since = "1.0.0")]
12381239
pub fn len(&self) -> usize {
12391240
self.vec.len()

src/librustc/infer/error_reporting.rs

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

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

src/libsyntax/feature_gate.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ declare_features! (
315315

316316
// Allows using `Self` and associated types in struct expressions and patterns.
317317
(active, more_struct_aliases, "1.14.0", Some(37544)),
318+
319+
// Allow safe suggestions for potential type conversions.
320+
(active, safe_suggestion, "1.0.0", Some(37384)),
318321
);
319322

320323
declare_features! (
@@ -649,6 +652,11 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
649652
"internal implementation detail",
650653
cfg_fn!(rustc_attrs))),
651654

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

0 commit comments

Comments
 (0)