Fix #58734.
/// 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 {
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);
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) => {
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
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!(
err.note(&violation.error_msg());
}
}
- err
+ Some(err)
}
}
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;
}
}
}
- 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;
}
} 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) {
--- /dev/null
+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`
+}
--- /dev/null
+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`.