Skip to content

Commit

Permalink
Elide object safety errors on non-existent trait function
Browse files Browse the repository at this point in the history
Fix #58734.
  • Loading branch information
estebank committed Mar 15, 2019
1 parent ad8a3eb commit d7bb98f
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
36 changes: 25 additions & 11 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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!(
Expand All @@ -1313,7 +1327,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
err.note(&violation.error_msg());
}
}
err
Some(err)
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
17 changes: 10 additions & 7 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/issues/issue-58734.rs
Original file line number Diff line number Diff line change
@@ -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`
}
11 changes: 11 additions & 0 deletions src/test/ui/issues/issue-58734.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit d7bb98f

Please sign in to comment.