Skip to content

Commit 4f7fc5a

Browse files
authored
Rollup merge of #69722 - estebank:negative-impl-span-ast, r=Centril
Tweak output for invalid negative impl AST errors Use more accurate spans for negative `impl` errors. r? @Centril
2 parents 3d23de7 + 7ee1b47 commit 4f7fc5a

29 files changed

+184
-141
lines changed

src/librustc_ast/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2118,14 +2118,14 @@ pub enum ImplPolarity {
21182118
/// `impl Trait for Type`
21192119
Positive,
21202120
/// `impl !Trait for Type`
2121-
Negative,
2121+
Negative(Span),
21222122
}
21232123

21242124
impl fmt::Debug for ImplPolarity {
21252125
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21262126
match *self {
21272127
ImplPolarity::Positive => "positive".fmt(f),
2128-
ImplPolarity::Negative => "negative".fmt(f),
2128+
ImplPolarity::Negative(_) => "negative".fmt(f),
21292129
}
21302130
}
21312131
}

src/librustc_ast_passes/ast_validation.rs

+77-49
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use rustc_ast::ast::*;
1010
use rustc_ast::attr;
1111
use rustc_ast::expand::is_proc_macro_attr;
12+
use rustc_ast::ptr::P;
1213
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
1314
use rustc_ast::walk_list;
1415
use rustc_ast_pretty::pprust;
@@ -594,6 +595,54 @@ impl<'a> AstValidator<'a> {
594595
.span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
595596
.emit();
596597
}
598+
599+
fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
600+
if !generics.params.is_empty() {
601+
struct_span_err!(
602+
self.session,
603+
generics.span,
604+
E0567,
605+
"auto traits cannot have generic parameters"
606+
)
607+
.span_label(ident_span, "auto trait cannot have generic parameters")
608+
.span_suggestion(
609+
generics.span,
610+
"remove the parameters",
611+
String::new(),
612+
Applicability::MachineApplicable,
613+
)
614+
.emit();
615+
}
616+
}
617+
618+
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
619+
if let [first @ last] | [first, .., last] = &bounds[..] {
620+
let span = first.span().to(last.span());
621+
struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
622+
.span_label(ident_span, "auto trait cannot have super traits")
623+
.span_suggestion(
624+
span,
625+
"remove the super traits",
626+
String::new(),
627+
Applicability::MachineApplicable,
628+
)
629+
.emit();
630+
}
631+
}
632+
633+
fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
634+
if !trait_items.is_empty() {
635+
let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
636+
struct_span_err!(
637+
self.session,
638+
spans,
639+
E0380,
640+
"auto traits cannot have methods or associated items"
641+
)
642+
.span_label(ident_span, "auto trait cannot have items")
643+
.emit();
644+
}
645+
}
597646
}
598647

599648
fn validate_generic_param_order<'a>(
@@ -779,7 +828,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
779828
defaultness: _,
780829
constness: _,
781830
generics: _,
782-
of_trait: Some(_),
831+
of_trait: Some(ref t),
783832
ref self_ty,
784833
items: _,
785834
} => {
@@ -794,13 +843,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
794843
.help("use `auto trait Trait {}` instead")
795844
.emit();
796845
}
797-
if let (Unsafe::Yes(span), ImplPolarity::Negative) = (unsafety, polarity) {
846+
if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
798847
struct_span_err!(
799848
this.session,
800-
item.span,
849+
sp.to(t.path.span),
801850
E0198,
802851
"negative impls cannot be unsafe"
803852
)
853+
.span_label(sp, "negative because of this")
804854
.span_label(span, "unsafe because of this")
805855
.emit();
806856
}
@@ -816,38 +866,36 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
816866
constness,
817867
generics: _,
818868
of_trait: None,
819-
self_ty: _,
869+
ref self_ty,
820870
items: _,
821871
} => {
872+
let error = |annotation_span, annotation| {
873+
let mut err = self.err_handler().struct_span_err(
874+
self_ty.span,
875+
&format!("inherent impls cannot be {}", annotation),
876+
);
877+
err.span_label(annotation_span, &format!("{} because of this", annotation));
878+
err.span_label(self_ty.span, "inherent impl for this type");
879+
err
880+
};
881+
822882
self.invalid_visibility(
823883
&item.vis,
824884
Some("place qualifiers on individual impl items instead"),
825885
);
826886
if let Unsafe::Yes(span) = unsafety {
827-
struct_span_err!(
828-
self.session,
829-
item.span,
830-
E0197,
831-
"inherent impls cannot be unsafe"
832-
)
833-
.span_label(span, "unsafe because of this")
834-
.emit();
887+
error(span, "unsafe").code(error_code!(E0197)).emit();
835888
}
836-
if polarity == ImplPolarity::Negative {
837-
self.err_handler().span_err(item.span, "inherent impls cannot be negative");
889+
if let ImplPolarity::Negative(span) = polarity {
890+
error(span, "negative").emit();
838891
}
839892
if let Defaultness::Default(def_span) = defaultness {
840-
let span = self.session.source_map().def_span(item.span);
841-
self.err_handler()
842-
.struct_span_err(span, "inherent impls cannot be `default`")
843-
.span_label(def_span, "`default` because of this")
893+
error(def_span, "`default`")
844894
.note("only trait implementations may be annotated with `default`")
845895
.emit();
846896
}
847897
if let Const::Yes(span) = constness {
848-
self.err_handler()
849-
.struct_span_err(item.span, "inherent impls cannot be `const`")
850-
.span_label(span, "`const` because of this")
898+
error(span, "`const`")
851899
.note("only trait implementations may be annotated with `const`")
852900
.emit();
853901
}
@@ -882,33 +930,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
882930
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
883931
if is_auto == IsAuto::Yes {
884932
// Auto traits cannot have generics, super traits nor contain items.
885-
if !generics.params.is_empty() {
886-
struct_span_err!(
887-
self.session,
888-
item.span,
889-
E0567,
890-
"auto traits cannot have generic parameters"
891-
)
892-
.emit();
893-
}
894-
if !bounds.is_empty() {
895-
struct_span_err!(
896-
self.session,
897-
item.span,
898-
E0568,
899-
"auto traits cannot have super traits"
900-
)
901-
.emit();
902-
}
903-
if !trait_items.is_empty() {
904-
struct_span_err!(
905-
self.session,
906-
item.span,
907-
E0380,
908-
"auto traits cannot have methods or associated items"
909-
)
910-
.emit();
911-
}
933+
self.deny_generic_params(generics, item.ident.span);
934+
self.deny_super_traits(bounds, item.ident.span);
935+
self.deny_items(trait_items, item.ident.span);
912936
}
913937
self.no_questions_in_bounds(bounds, "supertraits", true);
914938

@@ -1153,9 +1177,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11531177
}) = fk.header()
11541178
{
11551179
self.err_handler()
1156-
.struct_span_err(span, "functions cannot be both `const` and `async`")
1180+
.struct_span_err(
1181+
vec![*cspan, *aspan],
1182+
"functions cannot be both `const` and `async`",
1183+
)
11571184
.span_label(*cspan, "`const` because of this")
11581185
.span_label(*aspan, "`async` because of this")
1186+
.span_label(span, "") // Point at the fn header.
11591187
.emit();
11601188
}
11611189

src/librustc_ast_passes/feature_gate.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
337337
}
338338
}
339339

340-
ast::ItemKind::Impl { polarity, defaultness, .. } => {
341-
if polarity == ast::ImplPolarity::Negative {
340+
ast::ItemKind::Impl { polarity, defaultness, ref of_trait, .. } => {
341+
if let ast::ImplPolarity::Negative(span) = polarity {
342342
gate_feature_post!(
343343
&self,
344344
optin_builtin_traits,
345-
i.span,
345+
span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)),
346346
"negative trait bounds are not yet fully implemented; \
347-
use marker types for now"
347+
use marker types for now"
348348
);
349349
}
350350

src/librustc_ast_passes/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(bindings_after_at)]
12
//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
23
//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
34
//! by `rustc_ast_lowering`.

src/librustc_ast_pretty/pprust.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ impl<'a> State<'a> {
11601160
self.s.space();
11611161
}
11621162

1163-
if polarity == ast::ImplPolarity::Negative {
1163+
if let ast::ImplPolarity::Negative(_) = polarity {
11641164
self.s.word("!");
11651165
}
11661166

src/librustc_hir/print.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ impl<'a> State<'a> {
652652
self.word_nbsp("const");
653653
}
654654

655-
if let hir::ImplPolarity::Negative = polarity {
655+
if let hir::ImplPolarity::Negative(_) = polarity {
656656
self.s.word("!");
657657
}
658658

src/librustc_parse/parser/item.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,16 @@ impl<'a> Parser<'a> {
373373
self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
374374
}
375375

376+
fn parse_polarity(&mut self) -> ast::ImplPolarity {
377+
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
378+
if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
379+
self.bump(); // `!`
380+
ast::ImplPolarity::Negative(self.prev_token.span)
381+
} else {
382+
ast::ImplPolarity::Positive
383+
}
384+
}
385+
376386
/// Parses an implementation item.
377387
///
378388
/// ```
@@ -411,13 +421,7 @@ impl<'a> Parser<'a> {
411421
self.sess.gated_spans.gate(sym::const_trait_impl, span);
412422
}
413423

414-
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
415-
let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
416-
self.bump(); // `!`
417-
ast::ImplPolarity::Negative
418-
} else {
419-
ast::ImplPolarity::Positive
420-
};
424+
let polarity = self.parse_polarity();
421425

422426
// Parse both types and traits as a type, then reinterpret if necessary.
423427
let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span));

src/librustc_save_analysis/sig.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ impl Sig for ast::Item {
519519
text.push(' ');
520520

521521
let trait_sig = if let Some(ref t) = *of_trait {
522-
if polarity == ast::ImplPolarity::Negative {
522+
if let ast::ImplPolarity::Negative(_) = polarity {
523523
text.push('!');
524524
}
525525
let trait_sig = t.path.make(offset + text.len(), id, scx)?;

src/librustc_typeck/coherence/unsafety.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ impl UnsafetyChecker<'tcx> {
6969
.emit();
7070
}
7171

72-
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
72+
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
7373
// Reported in AST validation
7474
self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
7575
}
76-
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative)
76+
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
7777
| (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
7878
| (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
7979
| (Unsafety::Normal, None, Unsafety::Normal, _) => {

src/librustc_typeck/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,7 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
15481548
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
15491549
let item = tcx.hir().expect_item(hir_id);
15501550
match &item.kind {
1551-
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => {
1551+
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => {
15521552
if is_rustc_reservation {
15531553
tcx.sess.span_err(item.span, "reservation impls can't be negative");
15541554
}

src/test/ui/async-await/no-const-async.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: functions cannot be both `const` and `async`
2-
--> $DIR/no-const-async.rs:4:1
2+
--> $DIR/no-const-async.rs:4:5
33
|
44
LL | pub const async fn x() {}
5-
| ^^^^-----^-----^^^^^^^^^^
5+
| ----^^^^^-^^^^^----------
66
| | |
77
| | `async` because of this
88
| `const` because of this

src/test/ui/auto-trait-validation.stderr

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
error[E0567]: auto traits cannot have generic parameters
2-
--> $DIR/auto-trait-validation.rs:3:1
2+
--> $DIR/auto-trait-validation.rs:3:19
33
|
44
LL | auto trait Generic<T> {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^
5+
| -------^^^ help: remove the parameters
6+
| |
7+
| auto trait cannot have generic parameters
68

79
error[E0568]: auto traits cannot have super traits
8-
--> $DIR/auto-trait-validation.rs:5:1
10+
--> $DIR/auto-trait-validation.rs:5:20
911
|
1012
LL | auto trait Bound : Copy {}
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
| ----- ^^^^ help: remove the super traits
14+
| |
15+
| auto trait cannot have super traits
1216

1317
error[E0380]: auto traits cannot have methods or associated items
14-
--> $DIR/auto-trait-validation.rs:7:1
18+
--> $DIR/auto-trait-validation.rs:7:25
1519
|
1620
LL | auto trait MyTrait { fn foo() {} }
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
| ------- ^^^
22+
| |
23+
| auto trait cannot have items
1824

1925
error: aborting due to 3 previous errors
2026

src/test/ui/coherence/coherence-negative-impls-safe.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
error[E0198]: negative impls cannot be unsafe
2-
--> $DIR/coherence-negative-impls-safe.rs:7:1
2+
--> $DIR/coherence-negative-impls-safe.rs:7:13
33
|
44
LL | unsafe impl !Send for TestType {}
5-
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
5+
| ------ -^^^^
6+
| | |
7+
| | negative because of this
78
| unsafe because of this
89

910
error: aborting due to previous error

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0197]: inherent impls cannot be unsafe
2-
--> $DIR/E0197.rs:3:1
2+
--> $DIR/E0197.rs:3:13
33
|
44
LL | unsafe impl Foo { }
5-
| ------^^^^^^^^^^^^^
5+
| ------ ^^^ inherent impl for this type
66
| |
77
| unsafe because of this
88

0 commit comments

Comments
 (0)