Skip to content

Commit 8549cfe

Browse files
committed
Auto merge of #69649 - estebank:negative-impl-span, r=Centril
Tweak output for invalid negative impl errors Follow up to #69722. Tweak negative impl errors emitted in the HIR: ``` error[E0192]: invalid negative impl --> $DIR/E0192.rs:9:6 | LL | impl !Trait for Foo { } | ^^^^^^ | = note: negative impls are only allowed for auto traits, like `Send` and `Sync` ```
2 parents 5aa8f19 + b8f9866 commit 8549cfe

File tree

14 files changed

+95
-50
lines changed

14 files changed

+95
-50
lines changed

src/librustc_ast_lowering/item.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
402402
)
403403
});
404404

405+
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
406+
// to not cause an assertion failure inside the `lower_defaultness` function.
407+
let has_val = true;
408+
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
405409
hir::ItemKind::Impl {
406410
unsafety: self.lower_unsafety(unsafety),
407411
polarity,
408-
defaultness: self.lower_defaultness(defaultness, true /* [1] */),
412+
defaultness,
413+
defaultness_span,
409414
constness: self.lower_constness(constness),
410415
generics,
411416
of_trait: trait_ref,
@@ -434,9 +439,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
434439
panic!("`TyMac` should have been expanded by now")
435440
}
436441
}
437-
438-
// [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
439-
// not cause an assertion failure inside the `lower_defaultness` function.
440442
}
441443

442444
fn lower_const_item(
@@ -867,27 +869,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
867869
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
868870
};
869871

872+
// Since `default impl` is not yet implemented, this is always true in impls.
873+
let has_value = true;
874+
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
870875
hir::ImplItem {
871876
hir_id: self.lower_node_id(i.id),
872877
ident: i.ident,
873878
attrs: self.lower_attrs(&i.attrs),
874879
generics,
875880
vis: self.lower_visibility(&i.vis, None),
876-
defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
881+
defaultness,
877882
kind,
878883
span: i.span,
879884
}
880-
881-
// [1] since `default impl` is not yet implemented, this is always true in impls
882885
}
883886

884887
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
888+
// Since `default impl` is not yet implemented, this is always true in impls.
889+
let has_value = true;
890+
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
885891
hir::ImplItemRef {
886892
id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
887893
ident: i.ident,
888894
span: i.span,
889895
vis: self.lower_visibility(&i.vis, Some(i.id)),
890-
defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
896+
defaultness,
891897
kind: match &i.kind {
892898
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
893899
AssocItemKind::TyAlias(.., ty) => {
@@ -902,8 +908,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
902908
AssocItemKind::MacCall(..) => unimplemented!(),
903909
},
904910
}
905-
906-
// [1] since `default impl` is not yet implemented, this is always true in impls
907911
}
908912

909913
/// If an `explicit_owner` is given, this method allocates the `HirId` in
@@ -938,12 +942,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
938942
respan(v.span, node)
939943
}
940944

941-
fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
945+
fn lower_defaultness(
946+
&self,
947+
d: Defaultness,
948+
has_value: bool,
949+
) -> (hir::Defaultness, Option<Span>) {
942950
match d {
943-
Defaultness::Default(_) => hir::Defaultness::Default { has_value },
951+
Defaultness::Default(sp) => (hir::Defaultness::Default { has_value }, Some(sp)),
944952
Defaultness::Final => {
945953
assert!(has_value);
946-
hir::Defaultness::Final
954+
(hir::Defaultness::Final, None)
947955
}
948956
}
949957
}

src/librustc_hir/hir.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2153,7 +2153,7 @@ pub enum Defaultness {
21532153
impl Defaultness {
21542154
pub fn has_value(&self) -> bool {
21552155
match *self {
2156-
Defaultness::Default { has_value, .. } => has_value,
2156+
Defaultness::Default { has_value } => has_value,
21572157
Defaultness::Final => true,
21582158
}
21592159
}
@@ -2502,6 +2502,9 @@ pub enum ItemKind<'hir> {
25022502
unsafety: Unsafety,
25032503
polarity: ImplPolarity,
25042504
defaultness: Defaultness,
2505+
// We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
2506+
// decoding as `Span`s cannot be decoded when a `Session` is not available.
2507+
defaultness_span: Option<Span>,
25052508
constness: Constness,
25062509
generics: Generics<'hir>,
25072510

src/librustc_hir/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
590590
defaultness: _,
591591
polarity: _,
592592
constness: _,
593+
defaultness_span: _,
593594
ref generics,
594595
ref of_trait,
595596
ref self_ty,

src/librustc_hir/print.rs

+1
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ impl<'a> State<'a> {
632632
polarity,
633633
defaultness,
634634
constness,
635+
defaultness_span: _,
635636
ref generics,
636637
ref of_trait,
637638
ref self_ty,

src/librustc_typeck/check/wfcheck.rs

+27-11
Original file line numberDiff line numberDiff line change
@@ -98,34 +98,50 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
9898
//
9999
// won't be allowed unless there's an *explicit* implementation of `Send`
100100
// for `T`
101-
hir::ItemKind::Impl { defaultness, ref of_trait, ref self_ty, .. } => {
101+
hir::ItemKind::Impl {
102+
defaultness,
103+
defaultness_span,
104+
polarity,
105+
ref of_trait,
106+
ref self_ty,
107+
..
108+
} => {
102109
let is_auto = tcx
103110
.impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
104111
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
105-
let polarity = tcx.impl_polarity(def_id);
106112
if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
107-
tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
113+
let sp = of_trait.as_ref().map(|t| t.path.span).unwrap_or(item.span);
114+
let mut err =
115+
tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default");
116+
err.span_labels(defaultness_span, "default because of this");
117+
err.span_label(sp, "auto trait");
118+
err.emit();
108119
}
109-
match polarity {
110-
ty::ImplPolarity::Positive => {
120+
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
121+
match (tcx.impl_polarity(def_id), polarity) {
122+
(ty::ImplPolarity::Positive, _) => {
111123
check_impl(tcx, item, self_ty, of_trait);
112124
}
113-
ty::ImplPolarity::Negative => {
125+
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
114126
// FIXME(#27579): what amount of WF checking do we need for neg impls?
115-
if of_trait.is_some() && !is_auto {
127+
if let (Some(of_trait), false) = (of_trait, is_auto) {
116128
struct_span_err!(
117129
tcx.sess,
118-
item.span,
130+
span.to(of_trait.path.span),
119131
E0192,
120-
"negative impls are only allowed for \
121-
auto traits (e.g., `Send` and `Sync`)"
132+
"invalid negative impl"
133+
)
134+
.note(
135+
"negative impls are only allowed for auto traits, like `Send` and \
136+
`Sync`",
122137
)
123138
.emit()
124139
}
125140
}
126-
ty::ImplPolarity::Reservation => {
141+
(ty::ImplPolarity::Reservation, _) => {
127142
// FIXME: what amount of WF checking do we need for reservation impls?
128143
}
144+
_ => unreachable!(),
129145
}
130146
}
131147
hir::ItemKind::Fn(..) => {

src/librustc_typeck/collect.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1564,9 +1564,10 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
15641564
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
15651565
let item = tcx.hir().expect_item(hir_id);
15661566
match &item.kind {
1567-
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => {
1567+
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
15681568
if is_rustc_reservation {
1569-
tcx.sess.span_err(item.span, "reservation impls can't be negative");
1569+
let span = span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(*span));
1570+
tcx.sess.span_err(span, "reservation impls can't be negative");
15701571
}
15711572
ty::ImplPolarity::Negative
15721573
}

src/librustdoc/visit_ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
563563
polarity,
564564
defaultness,
565565
constness,
566+
defaultness_span: _,
566567
ref generics,
567568
ref of_trait,
568569
self_ty,

src/test/ui/error-codes/E0192.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
2-
--> $DIR/E0192.rs:9:1
1+
error[E0192]: invalid negative impl
2+
--> $DIR/E0192.rs:9:6
33
|
44
LL | impl !Trait for Foo { }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^
6+
|
7+
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
68

79
error: aborting due to previous error
810

src/test/ui/specialization/defaultimpl/validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be defau
1010
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
1111

1212
trait Tr {}
13-
default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
13+
default impl !Tr for S {} //~ ERROR invalid negative impl
1414

1515
fn main() {}

src/test/ui/specialization/defaultimpl/validation.stderr

+13-7
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,28 @@ LL | default impl S {}
99
= note: only trait implementations may be annotated with `default`
1010

1111
error: impls of auto traits cannot be default
12-
--> $DIR/validation.rs:9:1
12+
--> $DIR/validation.rs:9:21
1313
|
1414
LL | default unsafe impl Send for S {}
15-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
| ------- ^^^^ auto trait
16+
| |
17+
| default because of this
1618

1719
error: impls of auto traits cannot be default
18-
--> $DIR/validation.rs:10:1
20+
--> $DIR/validation.rs:10:15
1921
|
2022
LL | default impl !Send for Z {}
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
| ------- ^^^^ auto trait
24+
| |
25+
| default because of this
2226

23-
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
24-
--> $DIR/validation.rs:13:1
27+
error[E0192]: invalid negative impl
28+
--> $DIR/validation.rs:13:14
2529
|
2630
LL | default impl !Tr for S {}
27-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^
32+
|
33+
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
2834

2935
error: aborting due to 4 previous errors
3036

src/test/ui/syntax-trait-polarity.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ trait TestTrait {}
1212
unsafe impl !Send for TestType {}
1313
//~^ ERROR negative impls cannot be unsafe
1414
impl !TestTrait for TestType {}
15-
//~^ ERROR negative impls are only allowed for auto traits
15+
//~^ ERROR invalid negative impl
1616

1717
struct TestType2<T>(T);
1818

@@ -22,6 +22,6 @@ impl<T> !TestType2<T> {}
2222
unsafe impl<T> !Send for TestType2<T> {}
2323
//~^ ERROR negative impls cannot be unsafe
2424
impl<T> !TestTrait for TestType2<T> {}
25-
//~^ ERROR negative impls are only allowed for auto traits
25+
//~^ ERROR invalid negative impl
2626

2727
fn main() {}

src/test/ui/syntax-trait-polarity.stderr

+10-6
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,21 @@ LL | unsafe impl<T> !Send for TestType2<T> {}
3232
| | negative because of this
3333
| unsafe because of this
3434

35-
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
36-
--> $DIR/syntax-trait-polarity.rs:14:1
35+
error[E0192]: invalid negative impl
36+
--> $DIR/syntax-trait-polarity.rs:14:6
3737
|
3838
LL | impl !TestTrait for TestType {}
39-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
| ^^^^^^^^^^
40+
|
41+
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
4042

41-
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
42-
--> $DIR/syntax-trait-polarity.rs:24:1
43+
error[E0192]: invalid negative impl
44+
--> $DIR/syntax-trait-polarity.rs:24:9
4345
|
4446
LL | impl<T> !TestTrait for TestType2<T> {}
45-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
| ^^^^^^^^^^
48+
|
49+
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
4650

4751
error: aborting due to 6 previous errors
4852

src/test/ui/typeck/typeck-negative-impls-builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ trait TestTrait {
77
}
88

99
impl !TestTrait for TestType {}
10-
//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
10+
//~^ ERROR invalid negative impl
1111

1212
fn main() {}

src/test/ui/typeck/typeck-negative-impls-builtin.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
2-
--> $DIR/typeck-negative-impls-builtin.rs:9:1
1+
error[E0192]: invalid negative impl
2+
--> $DIR/typeck-negative-impls-builtin.rs:9:6
33
|
44
LL | impl !TestTrait for TestType {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^
6+
|
7+
= note: negative impls are only allowed for auto traits, like `Send` and `Sync`
68

79
error: aborting due to previous error
810

0 commit comments

Comments
 (0)