diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 68b067012d3fa72db822c122427a4fa21228484e..673a717b5f8e963f2c044a5a24ffb8ca015acb15 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 b4c41a99a6b971715f679d2e62a560c23cb7b2f7..a5017d5d7010f01aa74173da96080467ac05bfd3 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1231,6 +1231,7 @@ pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { /// 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 d50853e3a0e74f86384354824c763c97e13c8c31..98cbd742b1092fcb8be6b14d6c944426adb72675 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -587,19 +587,29 @@ pub fn note_type_err(&self, // 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, 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 @@ pub fn note_type_err(&self, self.tcx.note_and_explain_type_err(diag, terr, span); } + fn find_attr(&self, def_id: DefId, attr_name: &str) -> Option { + 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 77c53542dcbec3233b3480e812d52feb91ce967b..dbb31b0e56cd1b7e001355651725dec0ed82add1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -304,6 +304,7 @@ pub fn new() -> 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 @@ pub fn new() -> 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 fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, Att "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),