Skip to content

Commit 96836b9

Browse files
committed
Silence redundant warning when E0038 will be emitted
1 parent 78ef946 commit 96836b9

File tree

10 files changed

+45
-29
lines changed

10 files changed

+45
-29
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
605605
let violations =
606606
object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
607607
if !violations.is_empty() {
608-
report_object_safety_error(tcx, *span, trait_def_id, &violations).emit();
608+
report_object_safety_error(tcx, *span, None, trait_def_id, &violations).emit();
609609
object_safety_violations = true;
610610
}
611611
}

compiler/rustc_hir_analysis/src/astconv/lint.rs

+5
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
122122
],
123123
Applicability::MachineApplicable,
124124
);
125+
} else {
126+
// We'll emit the object safety error already, with a structured suggestion.
127+
diag.downgrade_to_delayed_bug();
125128
}
126129
return true;
127130
}
@@ -145,6 +148,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
145148
}
146149
if !is_object_safe {
147150
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
151+
// We'll emit the object safety error already, with a structured suggestion.
152+
diag.downgrade_to_delayed_bug();
148153
} else {
149154
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
150155
// There are more than one trait bound, we need surrounding parentheses.

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
140140
let reported = report_object_safety_error(
141141
tcx,
142142
span,
143+
Some(hir_id),
143144
item.trait_ref().def_id(),
144145
&object_safety_violations,
145146
)

compiler/rustc_infer/src/traits/error_reporting/mod.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;
22

33
use crate::infer::InferCtxt;
44
use rustc_data_structures::fx::FxIndexSet;
5-
use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan};
5+
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, MultiSpan};
66
use rustc_hir as hir;
77
use rustc_hir::def_id::{DefId, LocalDefId};
8+
use rustc_hir::intravisit::Map;
89
use rustc_middle::ty::print::with_no_trimmed_paths;
910
use rustc_middle::ty::{self, TyCtxt};
1011
use rustc_span::Span;
@@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
4243
pub fn report_object_safety_error<'tcx>(
4344
tcx: TyCtxt<'tcx>,
4445
span: Span,
46+
hir_id: Option<hir::HirId>,
4547
trait_def_id: DefId,
4648
violations: &[ObjectSafetyViolation],
4749
) -> DiagnosticBuilder<'tcx> {
@@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
5961
);
6062
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
6163

64+
if let Some(hir_id) = hir_id
65+
&& let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id)
66+
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
67+
{
68+
let mut hir_id = hir_id;
69+
while let hir::Node::Ty(ty) = tcx.hir().get_parent(hir_id) {
70+
hir_id = ty.hir_id;
71+
}
72+
if tcx.hir().get_parent(hir_id).fn_sig().is_some() {
73+
// Do not suggest `impl Trait` when dealing with things like super-traits.
74+
err.span_suggestion_verbose(
75+
ty.span.until(trait_ref.span),
76+
"consider using an opaque type instead",
77+
"impl ",
78+
Applicability::MaybeIncorrect,
79+
);
80+
}
81+
}
6282
let mut reported_violations = FxIndexSet::default();
6383
let mut multi_span = vec![];
6484
let mut messages = vec![];

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
816816

817817
ty::PredicateKind::ObjectSafe(trait_def_id) => {
818818
let violations = self.tcx.object_safety_violations(trait_def_id);
819-
report_object_safety_error(self.tcx, span, trait_def_id, violations)
819+
report_object_safety_error(self.tcx, span, None, trait_def_id, violations)
820820
}
821821

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

925925
TraitNotObjectSafe(did) => {
926926
let violations = self.tcx.object_safety_violations(did);
927-
report_object_safety_error(self.tcx, span, did, violations)
927+
report_object_safety_error(self.tcx, span, None, did, violations)
928928
}
929929

930930
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {

tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// run-rustfix
22
#![deny(bare_trait_objects)]
33
fn ord_prefer_dot(s: String) -> impl Ord {
4-
//~^ ERROR trait objects without an explicit `dyn` are deprecated
5-
//~| ERROR the trait `Ord` cannot be made into an object
6-
//~| WARNING this is accepted in the current edition (Rust 2015)
4+
//~^ ERROR the trait `Ord` cannot be made into an object
75
(s.starts_with("."), s)
86
}
97
fn main() {

tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// run-rustfix
22
#![deny(bare_trait_objects)]
33
fn ord_prefer_dot(s: String) -> Ord {
4-
//~^ ERROR trait objects without an explicit `dyn` are deprecated
5-
//~| ERROR the trait `Ord` cannot be made into an object
6-
//~| WARNING this is accepted in the current edition (Rust 2015)
4+
//~^ ERROR the trait `Ord` cannot be made into an object
75
(s.starts_with("."), s)
86
}
97
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,3 @@
1-
error: trait objects without an explicit `dyn` are deprecated
2-
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
3-
|
4-
LL | fn ord_prefer_dot(s: String) -> Ord {
5-
| ^^^
6-
|
7-
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
8-
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
9-
note: the lint level is defined here
10-
--> $DIR/bare-trait-dont-suggest-dyn.rs:2:9
11-
|
12-
LL | #![deny(bare_trait_objects)]
13-
| ^^^^^^^^^^^^^^^^^^
14-
help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type
15-
|
16-
LL | fn ord_prefer_dot(s: String) -> impl Ord {
17-
| ++++
18-
191
error[E0038]: the trait `Ord` cannot be made into an object
202
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
213
|
@@ -29,7 +11,11 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
2911
::: $SRC_DIR/core/src/cmp.rs:LL:COL
3012
|
3113
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
14+
help: consider using an opaque type instead
15+
|
16+
LL | fn ord_prefer_dot(s: String) -> impl Ord {
17+
| ++++
3218

33-
error: aborting due to 2 previous errors
19+
error: aborting due to 1 previous error
3420

3521
For more information about this error, try `rustc --explain E0038`.

tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ LL | trait Baz : Bar<Self> {
1111
| --- ^^^^^^^^^ ...because it uses `Self` as a type parameter
1212
| |
1313
| this trait cannot be made into an object...
14+
help: consider using an opaque type instead
15+
|
16+
LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
17+
| ~~~~
1418

1519
error: aborting due to 1 previous error
1620

tests/ui/traits/issue-28576.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ LL | pub trait Bar: Foo<Assoc=()> {
1414
| | | ...because it uses `Self` as a type parameter
1515
| | ...because it uses `Self` as a type parameter
1616
| this trait cannot be made into an object...
17+
help: consider using an opaque type instead
18+
|
19+
LL | impl Bar
20+
| ~~~~
1721

1822
error: aborting due to 1 previous error
1923

0 commit comments

Comments
 (0)