about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2016-10-25 22:19:19 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2016-12-20 11:37:15 +0100
commit164f0105bb65f31b89e5fb7f368c9e6f5833a3f8 (patch)
treec398440b210bd52fbfc2ffe6f98760fff9422450
parent601bbf26a89f178374278030d7821e2cc77437f7 (diff)
downloadrust-164f0105bb65f31b89e5fb7f368c9e6f5833a3f8.tar.gz
rust-164f0105bb65f31b89e5fb7f368c9e6f5833a3f8.zip
Add safe_suggestion attribute
-rw-r--r--src/libcollections/lib.rs1
-rw-r--r--src/libcollections/string.rs1
-rw-r--r--src/librustc/infer/error_reporting.rs29
-rw-r--r--src/libsyntax/feature_gate.rs9
4 files changed, 35 insertions, 5 deletions
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 68b067012d3..673a717b5f8 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -28,6 +28,7 @@
 
 #![cfg_attr(test, allow(deprecated))] // rand
 #![cfg_attr(not(stage0), deny(warnings))]
+#![cfg_attr(not(stage0), feature(safe_suggestion))]
 
 #![feature(alloc)]
 #![feature(allow_internal_unstable)]
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index b4c41a99a6b..a5017d5d701 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1231,6 +1231,7 @@ impl String {
     /// assert_eq!(a.len(), 3);
     /// ```
     #[inline]
+    #[cfg_attr(not(stage0), safe_suggestion)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.vec.len()
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index d50853e3a0e..98cbd742b10 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -587,19 +587,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // look for expected with found id
                 self.tcx.populate_inherent_implementations_for_type_if_necessary(found);
                 if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&found) {
-                    let mut methods = Vec::new();
+                    let mut methods: Vec<(Option<ast::Attribute>, DefId, ImplOrTraitItem<'tcx>)> = Vec::new();
                     for impl_ in impl_infos {
                         methods.append(&mut self.tcx
                                                 .impl_or_trait_items(*impl_)
                                                 .iter()
-                                                .map(|&did| self.tcx.impl_or_trait_item(did))
-                                                .filter(|x| {
+                                                .map(|&did| (None, did, self.tcx.impl_or_trait_item(did)))
+                                                .filter(|&(_, _, ref x)| {
                                                     self.matches_return_type(x, &expected_ty)
                                                 })
                                                 .collect());
                     }
-                    for method in methods {
-                        println!("==> {:?}", method.name());
+                    let safe_suggestions: Vec<_> = methods.iter()
+                                                  .map(|&(_, ref id, ref x)| (self.find_attr(*id, "safe_suggestion"), id, x))
+                                                  .filter(|&(ref res, _, _)| res.is_some())
+                                                  .collect();
+                    if safe_suggestions.len() > 0 {
+                        for (_, _, method) in safe_suggestions {
+                            println!("safe ==> {:?}", method.name());
+                        }
+                    } else {
+                        for &(_, _, ref method) in methods.iter() {
+                            println!("not safe ==> {:?}", method.name());
+                        }
                     }
                 }
             }
@@ -615,6 +625,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.tcx.note_and_explain_type_err(diag, terr, span);
     }
 
+    fn find_attr(&self, def_id: DefId, attr_name: &str) -> Option<ast::Attribute> {
+        for item in self.tcx.get_attrs(def_id).iter() {
+            if item.check_name(attr_name) {
+                return Some(item.clone());
+            }
+        }
+        None
+    }
+
     pub fn report_and_explain_type_error(&self,
                                          trace: TypeTrace<'tcx>,
                                          terr: &TypeError<'tcx>)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 77c53542dcb..dbb31b0e56c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -304,6 +304,7 @@ declare_features! (
     // Allows using `Self` and associated types in struct expressions and patterns.
     (active, more_struct_aliases, "1.14.0", Some(37544)),
 
+
     // Allows #[link(..., cfg(..))]
     (active, link_cfg, "1.14.0", Some(37406)),
 
@@ -314,6 +315,9 @@ declare_features! (
 
     // Allows #[target_feature(...)]
     (active, target_feature, "1.15.0", None),
+
+    // Allow safe suggestions for potential type conversions.
+    (active, safe_suggestion, "1.0.0", Some(37384)),
 );
 
 declare_features! (
@@ -648,6 +652,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                                    "internal implementation detail",
                                                    cfg_fn!(rustc_attrs))),
 
+    ("safe_suggestion", Whitelisted, Gated("safe_suggestion",
+                                           "the `#[safe_suggestion]` attribute \
+                                            is an experimental feature",
+                                           cfg_fn!(safe_suggestion))),
+
     // FIXME: #14408 whitelist docs since rustdoc looks at them
     ("doc", Whitelisted, Ungated),