Skip to content

Commit

Permalink
Silence redundant warning when E0038 will be emitted
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Jan 3, 2024
1 parent 78ef946 commit 96836b9
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 29 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/astconv/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let violations =
object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
if !violations.is_empty() {
report_object_safety_error(tcx, *span, trait_def_id, &violations).emit();
report_object_safety_error(tcx, *span, None, trait_def_id, &violations).emit();
object_safety_violations = true;
}
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir_analysis/src/astconv/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
],
Applicability::MachineApplicable,
);
} else {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
return true;
}
Expand All @@ -145,6 +148,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if !is_object_safe {
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
} else {
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
// There are more than one trait bound, we need surrounding parentheses.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/astconv/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let reported = report_object_safety_error(
tcx,
span,
Some(hir_id),
item.trait_ref().def_id(),
&object_safety_violations,
)
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_infer/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;

use crate::infer::InferCtxt;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Map;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
Expand Down Expand Up @@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn report_object_safety_error<'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
hir_id: Option<hir::HirId>,
trait_def_id: DefId,
violations: &[ObjectSafetyViolation],
) -> DiagnosticBuilder<'tcx> {
Expand All @@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
);
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));

if let Some(hir_id) = hir_id
&& let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id)
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
{
let mut hir_id = hir_id;
while let hir::Node::Ty(ty) = tcx.hir().get_parent(hir_id) {
hir_id = ty.hir_id;
}
if tcx.hir().get_parent(hir_id).fn_sig().is_some() {
// Do not suggest `impl Trait` when dealing with things like super-traits.
err.span_suggestion_verbose(
ty.span.until(trait_ref.span),
"consider using an opaque type instead",
"impl ",
Applicability::MaybeIncorrect,
);
}
}
let mut reported_violations = FxIndexSet::default();
let mut multi_span = vec![];
let mut messages = vec![];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {

ty::PredicateKind::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
report_object_safety_error(self.tcx, span, trait_def_id, violations)
report_object_safety_error(self.tcx, span, None, trait_def_id, violations)
}

ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
Expand Down Expand Up @@ -924,7 +924,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {

TraitNotObjectSafe(did) => {
let violations = self.tcx.object_safety_violations(did);
report_object_safety_error(self.tcx, span, did, violations)
report_object_safety_error(self.tcx, span, None, did, violations)
}

SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// run-rustfix
#![deny(bare_trait_objects)]
fn ord_prefer_dot(s: String) -> impl Ord {
//~^ ERROR trait objects without an explicit `dyn` are deprecated
//~| ERROR the trait `Ord` cannot be made into an object
//~| WARNING this is accepted in the current edition (Rust 2015)
//~^ ERROR the trait `Ord` cannot be made into an object
(s.starts_with("."), s)
}
fn main() {
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// run-rustfix
#![deny(bare_trait_objects)]
fn ord_prefer_dot(s: String) -> Ord {
//~^ ERROR trait objects without an explicit `dyn` are deprecated
//~| ERROR the trait `Ord` cannot be made into an object
//~| WARNING this is accepted in the current edition (Rust 2015)
//~^ ERROR the trait `Ord` cannot be made into an object
(s.starts_with("."), s)
}
fn main() {
Expand Down
24 changes: 5 additions & 19 deletions tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
|
LL | fn ord_prefer_dot(s: String) -> Ord {
| ^^^
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/bare-trait-dont-suggest-dyn.rs:2:9
|
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type
|
LL | fn ord_prefer_dot(s: String) -> impl Ord {
| ++++

error[E0038]: the trait `Ord` cannot be made into an object
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
|
Expand All @@ -29,7 +11,11 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
::: $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
|
LL | fn ord_prefer_dot(s: String) -> impl Ord {
| ++++

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0038`.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ LL | trait Baz : Bar<Self> {
| --- ^^^^^^^^^ ...because it uses `Self` as a type parameter
| |
| this trait cannot be made into an object...
help: consider using an opaque type instead
|
LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
| ~~~~

error: aborting due to 1 previous error

Expand Down
4 changes: 4 additions & 0 deletions tests/ui/traits/issue-28576.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ LL | pub trait Bar: Foo<Assoc=()> {
| | | ...because it uses `Self` as a type parameter
| | ...because it uses `Self` as a type parameter
| this trait cannot be made into an object...
help: consider using an opaque type instead
|
LL | impl Bar
| ~~~~

error: aborting due to 1 previous error

Expand Down

0 comments on commit 96836b9

Please sign in to comment.