about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-03-04 19:24:52 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-03-15 13:26:30 -0700
commitd7bb98f7a1367918a8c74a620dd2c69831ddae7a (patch)
tree131f1a05b4510512d4c952d9605db14693ca6fc1
parentad8a3eb039ca3dc1ff5a3d5757afc5e5330c1bce (diff)
downloadrust-d7bb98f7a1367918a8c74a620dd2c69831ddae7a.tar.gz
rust-d7bb98f7a1367918a8c74a620dd2c69831ddae7a.zip
Elide object safety errors on non-existent trait function
Fix #58734.
-rw-r--r--src/librustc/session/mod.rs4
-rw-r--r--src/librustc/traits/error_reporting.rs36
-rw-r--r--src/librustc_typeck/astconv.rs5
-rw-r--r--src/librustc_typeck/check/method/suggest.rs17
-rw-r--r--src/test/ui/issues/issue-58734.rs22
-rw-r--r--src/test/ui/issues/issue-58734.stderr11
6 files changed, 74 insertions, 21 deletions
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 75a0a8195bc..7fc5ce67844 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -164,6 +164,9 @@ pub struct Session {
 
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
+
+    /// `Span`s of trait methods that weren't found to avoid emitting object safety errors
+    pub trait_methods_not_found: OneThread<RefCell<FxHashSet<Span>>>,
 }
 
 pub struct PerfStats {
@@ -1230,6 +1233,7 @@ fn build_session_(
         has_global_allocator: Once::new(),
         has_panic_handler: Once::new(),
         driver_lint_caps,
+        trait_methods_not_found: OneThread::new(RefCell::new(Default::default())),
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 6c8fe0875b6..f5f2ec38bdf 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -754,9 +754,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     ty::Predicate::ObjectSafe(trait_def_id) => {
                         let violations = self.tcx.global_tcx()
                             .object_safety_violations(trait_def_id);
-                        self.tcx.report_object_safety_error(span,
-                                                            trait_def_id,
-                                                            violations)
+                        if let Some(err) = self.tcx.report_object_safety_error(
+                            span,
+                            trait_def_id,
+                            violations,
+                        ) {
+                            err
+                        } else {
+                            return;
+                        }
                     }
 
                     ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
@@ -884,7 +890,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.global_tcx().object_safety_violations(did);
-                self.tcx.report_object_safety_error(span, did, violations)
+                if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
+                    err
+                } else {
+                    return;
+                }
             }
 
             // already reported in the query
@@ -1293,12 +1303,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         err
     }
 
-    pub fn report_object_safety_error(self,
-                                      span: Span,
-                                      trait_def_id: DefId,
-                                      violations: Vec<ObjectSafetyViolation>)
-                                      -> DiagnosticBuilder<'tcx>
-    {
+    pub fn report_object_safety_error(
+        self,
+        span: Span,
+        trait_def_id: DefId,
+        violations: Vec<ObjectSafetyViolation>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        if self.sess.trait_methods_not_found.borrow().contains(&span) {
+            // Avoid emitting error caused by non-existing method (#58734)
+            return None;
+        }
         let trait_str = self.def_path_str(trait_def_id);
         let span = self.sess.source_map().def_span(span);
         let mut err = struct_span_err!(
@@ -1313,7 +1327,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 err.note(&violation.error_msg());
             }
         }
-        err
+        Some(err)
     }
 }
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9ca75566b42..22fa3dcfb52 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1012,9 +1012,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         let object_safety_violations =
             tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
         if !object_safety_violations.is_empty() {
-            tcx.report_object_safety_error(
-                span, principal.def_id(), object_safety_violations)
-               .emit();
+            tcx.report_object_safety_error(span, principal.def_id(), object_safety_violations)
+                .map(|mut err| err.emit());
             return tcx.types.err;
         }
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index b4a1a2d76c2..5088c5069ba 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -60,13 +60,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn report_method_error<'b>(&self,
-                                   span: Span,
-                                   rcvr_ty: Ty<'tcx>,
-                                   item_name: ast::Ident,
-                                   source: SelfSource<'b>,
-                                   error: MethodError<'tcx>,
-                                   args: Option<&'gcx [hir::Expr]>) {
+    pub fn report_method_error<'b>(
+        &self,
+        span: Span,
+        rcvr_ty: Ty<'tcx>,
+        item_name: ast::Ident,
+        source: SelfSource<'b>,
+        error: MethodError<'tcx>,
+        args: Option<&'gcx [hir::Expr]>,
+    ) {
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
             return;
@@ -373,6 +375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     }
                 } else {
                     err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
+                    self.tcx.sess.trait_methods_not_found.borrow_mut().insert(span);
                 }
 
                 if self.is_fn_ty(&rcvr_ty, span) {
diff --git a/src/test/ui/issues/issue-58734.rs b/src/test/ui/issues/issue-58734.rs
new file mode 100644
index 00000000000..bbdfebe1577
--- /dev/null
+++ b/src/test/ui/issues/issue-58734.rs
@@ -0,0 +1,22 @@
+trait Trait {
+    fn exists(self) -> ();
+
+    fn not_object_safe() -> Self;
+}
+
+impl Trait for () {
+    fn exists(self) -> () {
+    }
+
+    fn not_object_safe() -> Self {
+        ()
+    }
+}
+
+fn main() {
+    // object-safe or not, this call is OK
+    Trait::exists(());
+    // no object safety error
+    Trait::nonexistent(());
+    //~^ ERROR no function or associated item named `nonexistent` found for type `dyn Trait`
+}
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
new file mode 100644
index 00000000000..d2f356df7ce
--- /dev/null
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -0,0 +1,11 @@
+error[E0599]: no function or associated item named `nonexistent` found for type `dyn Trait` in the current scope
+  --> $DIR/issue-58734.rs:20:12
+   |
+LL |     Trait::nonexistent(());
+   |     -------^^^^^^^^^^^
+   |     |
+   |     function or associated item not found in `dyn Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.