Skip to content

Commit 1d41c2c

Browse files
committed
Merge unboxed trait object error suggestion into regular dyn incompat error
1 parent ed44c0e commit 1d41c2c

19 files changed

+92
-221
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,6 @@ fn check_trait_item<'tcx>(
382382
_ => (None, trait_item.span),
383383
};
384384

385-
check_dyn_incompatible_self_trait_by_name(tcx, trait_item);
386-
387385
// Check that an item definition in a subtrait is shadowing a supertrait item.
388386
lint_item_shadowing_supertrait_item(tcx, def_id);
389387

@@ -832,70 +830,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
832830
}
833831
}
834832

835-
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
836-
match ty.kind {
837-
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
838-
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
839-
_ => false,
840-
},
841-
_ => false,
842-
}
843-
}
844-
845-
/// Detect when a dyn-incompatible trait is referring to itself in one of its associated items.
846-
///
847-
/// In such cases, suggest using `Self` instead.
848-
fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
849-
let (trait_ident, trait_def_id) =
850-
match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) {
851-
hir::Node::Item(item) => match item.kind {
852-
hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id),
853-
_ => return,
854-
},
855-
_ => return,
856-
};
857-
let mut trait_should_be_self = vec![];
858-
match &item.kind {
859-
hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty))
860-
if could_be_self(trait_def_id.def_id, ty) =>
861-
{
862-
trait_should_be_self.push(ty.span)
863-
}
864-
hir::TraitItemKind::Fn(sig, _) => {
865-
for ty in sig.decl.inputs {
866-
if could_be_self(trait_def_id.def_id, ty) {
867-
trait_should_be_self.push(ty.span);
868-
}
869-
}
870-
match sig.decl.output {
871-
hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => {
872-
trait_should_be_self.push(ty.span);
873-
}
874-
_ => {}
875-
}
876-
}
877-
_ => {}
878-
}
879-
if !trait_should_be_self.is_empty() {
880-
if tcx.is_dyn_compatible(trait_def_id) {
881-
return;
882-
}
883-
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
884-
tcx.dcx()
885-
.struct_span_err(
886-
trait_should_be_self,
887-
"associated item referring to unboxed trait object for its own trait",
888-
)
889-
.with_span_label(trait_ident.span, "in this trait")
890-
.with_multipart_suggestion(
891-
"you might have meant to use `Self` to refer to the implementing type",
892-
sugg,
893-
Applicability::MachineApplicable,
894-
)
895-
.emit();
896-
}
897-
}
898-
899833
fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {
900834
let item_name = tcx.item_name(trait_item_def_id.to_def_id());
901835
let trait_def_id = tcx.local_parent(trait_item_def_id);

compiler/rustc_hir_analysis/src/hir_wf_check.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use rustc_hir::def::DefKind;
12
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
23
use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind};
34
use rustc_infer::infer::TyCtxtInferExt;
4-
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
5+
use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc};
56
use rustc_middle::bug;
67
use rustc_middle::query::Providers;
78
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
@@ -107,6 +108,17 @@ fn diagnostic_hir_wf_check<'tcx>(
107108
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
108109
if self.depth >= self.cause_depth {
109110
self.cause = Some(error.obligation.cause);
111+
if let hir::TyKind::TraitObject(..) = ty.kind {
112+
if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn =
113+
self.tcx.def_kind(self.def_id)
114+
{
115+
self.cause = Some(ObligationCause::new(
116+
ty.span,
117+
self.def_id,
118+
ObligationCauseCode::DynCompatible(ty.span),
119+
));
120+
}
121+
}
110122
self.cause_depth = self.depth
111123
}
112124
}

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ pub enum ObligationCauseCode<'tcx> {
397397

398398
RustCall,
399399

400+
DynCompatible(Span),
401+
400402
/// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than
401403
/// the ADT it's being implemented for.
402404
AlwaysApplicableImpl,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2721,6 +2721,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27212721
ObligationCauseCode::TupleElem => {
27222722
err.note("only the last element of a tuple may have a dynamically sized type");
27232723
}
2724+
ObligationCauseCode::DynCompatible(span) => {
2725+
err.multipart_suggestion(
2726+
"you might have meant to use `Self` to refer to the implementing type",
2727+
vec![(span, "Self".into())],
2728+
Applicability::MachineApplicable,
2729+
);
2730+
}
27242731
ObligationCauseCode::WhereClause(item_def_id, span)
27252732
| ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
27262733
| ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..)

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::traits::{
3131
///
3232
/// Currently that is `Self` in supertraits. This is needed
3333
/// because `dyn_compatibility_violations` can't be used during
34-
/// type collection.
34+
/// type collection, as type collection is needed for `dyn_compatiblity_violations` itself.
3535
#[instrument(level = "debug", skip(tcx), ret)]
3636
pub fn hir_ty_lowering_dyn_compatibility_violations(
3737
tcx: TyCtxt<'_>,

tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ help: alternatively, consider constraining `g` so it does not apply to trait obj
8787
|
8888
LL | trait A { fn g(b: B) -> B where Self: Sized; }
8989
| +++++++++++++++++
90+
help: you might have meant to use `Self` to refer to the implementing type
91+
|
92+
LL - trait B { fn f(a: A) -> A; }
93+
LL + trait B { fn f(a: Self) -> A; }
94+
|
9095

9196
warning: trait objects without an explicit `dyn` are deprecated
9297
--> $DIR/avoid-ice-on-warning-3.rs:14:19
@@ -124,6 +129,11 @@ help: alternatively, consider constraining `f` so it does not apply to trait obj
124129
|
125130
LL | trait B { fn f(a: A) -> A where Self: Sized; }
126131
| +++++++++++++++++
132+
help: you might have meant to use `Self` to refer to the implementing type
133+
|
134+
LL - trait A { fn g(b: B) -> B; }
135+
LL + trait A { fn g(b: Self) -> B; }
136+
|
127137

128138
error: aborting due to 2 previous errors; 6 warnings emitted
129139

tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ trait GatTrait {
88

99
trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
1010
fn c(&self) -> dyn SuperTrait<T>;
11-
//~^ ERROR associated item referring to unboxed trait object for its own trait
12-
//~| ERROR the trait `SuperTrait` is not dyn compatible
11+
//~^ ERROR the trait `SuperTrait` is not dyn compatible
1312
}
1413

1514
fn main() {}

tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,6 @@ LL | Self: 'a;
77
| ^^
88
= help: consider adding an explicit lifetime bound `Self: 'a`...
99

10-
error: associated item referring to unboxed trait object for its own trait
11-
--> $DIR/supertrait-mentions-GAT.rs:10:20
12-
|
13-
LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
14-
| ---------- in this trait
15-
LL | fn c(&self) -> dyn SuperTrait<T>;
16-
| ^^^^^^^^^^^^^^^^^
17-
|
18-
help: you might have meant to use `Self` to refer to the implementing type
19-
|
20-
LL - fn c(&self) -> dyn SuperTrait<T>;
21-
LL + fn c(&self) -> Self;
22-
|
23-
2410
error[E0038]: the trait `SuperTrait` is not dyn compatible
2511
--> $DIR/supertrait-mentions-GAT.rs:10:20
2612
|
@@ -37,8 +23,13 @@ LL | type Gat<'a>
3723
LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
3824
| ---------- this trait is not dyn compatible...
3925
= help: consider moving `Gat` to another trait
26+
help: you might have meant to use `Self` to refer to the implementing type
27+
|
28+
LL - fn c(&self) -> dyn SuperTrait<T>;
29+
LL + fn c(&self) -> Self;
30+
|
4031

41-
error: aborting due to 3 previous errors
32+
error: aborting due to 2 previous errors
4233

4334
Some errors have detailed explanations: E0038, E0311.
4435
For more information about an error, try `rustc --explain E0038`.

tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@ trait A: Sized {
44
fn f(a: A) -> A;
55
//~^ ERROR expected a type, found a trait
66
//~| ERROR expected a type, found a trait
7-
//~| ERROR associated item referring to unboxed trait object for its own trait
87
}
98
trait B {
109
fn f(b: B) -> B;
1110
//~^ ERROR expected a type, found a trait
1211
//~| ERROR expected a type, found a trait
13-
//~| ERROR associated item referring to unboxed trait object for its own trait
1412
}
1513
trait C {
1614
fn f(&self, c: C) -> C;
1715
//~^ ERROR expected a type, found a trait
1816
//~| ERROR expected a type, found a trait
19-
//~| ERROR associated item referring to unboxed trait object for its own trait
2017
}
2118

2219
fn main() {}

tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,8 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as
2626
LL | fn f(a: A) -> impl A;
2727
| ++++
2828

29-
error: associated item referring to unboxed trait object for its own trait
30-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13
31-
|
32-
LL | trait A: Sized {
33-
| - in this trait
34-
LL | fn f(a: A) -> A;
35-
| ^ ^
36-
|
37-
help: you might have meant to use `Self` to refer to the implementing type
38-
|
39-
LL - fn f(a: A) -> A;
40-
LL + fn f(a: Self) -> Self;
41-
|
42-
4329
error[E0782]: expected a type, found a trait
44-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13
30+
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:9:13
4531
|
4632
LL | fn f(b: B) -> B;
4733
| ^
@@ -58,7 +44,7 @@ LL | fn f(b: impl B) -> B;
5844
| ++++
5945

6046
error[E0782]: expected a type, found a trait
61-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:19
47+
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:9:19
6248
|
6349
LL | fn f(b: B) -> B;
6450
| ^
@@ -68,22 +54,8 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as
6854
LL | fn f(b: B) -> impl B;
6955
| ++++
7056

71-
error: associated item referring to unboxed trait object for its own trait
72-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13
73-
|
74-
LL | trait B {
75-
| - in this trait
76-
LL | fn f(b: B) -> B;
77-
| ^ ^
78-
|
79-
help: you might have meant to use `Self` to refer to the implementing type
80-
|
81-
LL - fn f(b: B) -> B;
82-
LL + fn f(b: Self) -> Self;
83-
|
84-
8557
error[E0782]: expected a type, found a trait
86-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20
58+
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:14:20
8759
|
8860
LL | fn f(&self, c: C) -> C;
8961
| ^
@@ -100,7 +72,7 @@ LL | fn f(&self, c: impl C) -> C;
10072
| ++++
10173

10274
error[E0782]: expected a type, found a trait
103-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:26
75+
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:14:26
10476
|
10577
LL | fn f(&self, c: C) -> C;
10678
| ^
@@ -110,20 +82,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as
11082
LL | fn f(&self, c: C) -> impl C;
11183
| ++++
11284

113-
error: associated item referring to unboxed trait object for its own trait
114-
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20
115-
|
116-
LL | trait C {
117-
| - in this trait
118-
LL | fn f(&self, c: C) -> C;
119-
| ^ ^
120-
|
121-
help: you might have meant to use `Self` to refer to the implementing type
122-
|
123-
LL - fn f(&self, c: C) -> C;
124-
LL + fn f(&self, c: Self) -> Self;
125-
|
126-
127-
error: aborting due to 9 previous errors
85+
error: aborting due to 6 previous errors
12886

12987
For more information about this error, try `rustc --explain E0782`.

tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
#![allow(bare_trait_objects)]
33
trait A: Sized {
44
fn f(a: dyn A) -> dyn A;
5-
//~^ ERROR associated item referring to unboxed trait object for its own trait
6-
//~| ERROR the trait `A` is not dyn compatible
5+
//~^ ERROR the trait `A` is not dyn compatible
76
}
87
trait B {
98
fn f(a: dyn B) -> dyn B;
10-
//~^ ERROR associated item referring to unboxed trait object for its own trait
11-
//~| ERROR the trait `B` is not dyn compatible
9+
//~^ ERROR the trait `B` is not dyn compatible
1210
}
1311
trait C {
1412
fn f(&self, a: dyn C) -> dyn C;

0 commit comments

Comments
 (0)