Skip to content

Commit 16362c7

Browse files
committed
Auto merge of #47843 - estebank:teach, r=nikomatsakis
Add `-Zteach` documentation Add extra inline documentation to E0019, E0016, E0013, E0396, E0017, E0018, E0010, E0022, E0030, E0029, E0033, E0026 and E0027. Follow up to #47652.
2 parents b54f27b + 51f0c0d commit 16362c7

File tree

486 files changed

+3255
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

486 files changed

+3255
-55
lines changed

src/librustc/middle/entry.rs

+4
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ fn configure_main(this: &mut EntryContext) {
175175
err.emit();
176176
this.session.abort_if_errors();
177177
} else {
178+
if this.session.teach(&err.get_code().unwrap()) {
179+
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
180+
to get started: https://doc.rust-lang.org/book/");
181+
}
178182
err.emit();
179183
}
180184
}

src/librustc_mir/transform/qualify_consts.rs

+138-30
Original file line numberDiff line numberDiff line change
@@ -170,18 +170,40 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
170170
fn not_const(&mut self) {
171171
self.add(Qualif::NOT_CONST);
172172
if self.mode != Mode::Fn {
173-
span_err!(self.tcx.sess, self.span, E0019,
174-
"{} contains unimplemented expression type", self.mode);
173+
let mut err = struct_span_err!(
174+
self.tcx.sess,
175+
self.span,
176+
E0019,
177+
"{} contains unimplemented expression type",
178+
self.mode
179+
);
180+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
181+
err.note("A function call isn't allowed in the const's initialization expression \
182+
because the expression's value must be known at compile-time.");
183+
err.note("Remember: you can't use a function call inside a const's initialization \
184+
expression! However, you can use it anywhere else.");
185+
}
186+
err.emit();
175187
}
176188
}
177189

178190
/// Error about extra statements in a constant.
179191
fn statement_like(&mut self) {
180192
self.add(Qualif::NOT_CONST);
181193
if self.mode != Mode::Fn {
182-
span_err!(self.tcx.sess, self.span, E0016,
183-
"blocks in {}s are limited to items and tail expressions",
184-
self.mode);
194+
let mut err = struct_span_err!(
195+
self.tcx.sess,
196+
self.span,
197+
E0016,
198+
"blocks in {}s are limited to items and tail expressions",
199+
self.mode
200+
);
201+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
202+
err.note("Blocks in constants may only contain items (such as constant, function \
203+
definition, etc...) and a tail expression.");
204+
err.help("To avoid it, you have to replace the non-item object.");
205+
}
206+
err.emit();
185207
}
186208
}
187209

@@ -475,9 +497,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
475497
}
476498

477499
if self.mode == Mode::Const || self.mode == Mode::ConstFn {
478-
span_err!(self.tcx.sess, self.span, E0013,
479-
"{}s cannot refer to statics, use \
480-
a constant instead", self.mode);
500+
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
501+
"{}s cannot refer to statics, use \
502+
a constant instead", self.mode);
503+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
504+
err.note(
505+
"Static and const variables can refer to other const variables. But a \
506+
const variable cannot refer to a static variable."
507+
);
508+
err.help(
509+
"To fix this, the value can be extracted as a const and then used."
510+
);
511+
}
512+
err.emit()
481513
}
482514
}
483515
Place::Projection(ref proj) => {
@@ -498,13 +530,25 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
498530
if let ty::TyRawPtr(_) = base_ty.sty {
499531
this.add(Qualif::NOT_CONST);
500532
if this.mode != Mode::Fn {
501-
struct_span_err!(this.tcx.sess,
502-
this.span, E0396,
533+
let mut err = struct_span_err!(
534+
this.tcx.sess,
535+
this.span,
536+
E0396,
503537
"raw pointers cannot be dereferenced in {}s",
504-
this.mode)
505-
.span_label(this.span,
506-
"dereference of raw pointer in constant")
507-
.emit();
538+
this.mode
539+
);
540+
err.span_label(this.span,
541+
"dereference of raw pointer in constant");
542+
if this.tcx.sess.teach(&err.get_code().unwrap()) {
543+
err.note(
544+
"The value behind a raw pointer can't be determined \
545+
at compile-time (or even link-time), which means it \
546+
can't be used in a constant expression."
547+
);
548+
err.help("A possible fix is to dereference your pointer \
549+
at some point in run-time.");
550+
}
551+
err.emit();
508552
}
509553
}
510554
}
@@ -623,12 +667,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
623667
if !allow {
624668
self.add(Qualif::NOT_CONST);
625669
if self.mode != Mode::Fn {
626-
struct_span_err!(self.tcx.sess, self.span, E0017,
627-
"references in {}s may only refer \
628-
to immutable values", self.mode)
629-
.span_label(self.span, format!("{}s require immutable values",
630-
self.mode))
631-
.emit();
670+
let mut err = struct_span_err!(self.tcx.sess, self.span, E0017,
671+
"references in {}s may only refer \
672+
to immutable values", self.mode);
673+
err.span_label(self.span, format!("{}s require immutable values",
674+
self.mode));
675+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
676+
err.note("References in statics and constants may only refer to \
677+
immutable values.\n\n\
678+
Statics are shared everywhere, and if they refer to \
679+
mutable data one might violate memory safety since \
680+
holding multiple mutable references to shared data is \
681+
not allowed.\n\n\
682+
If you really want global mutable state, try using \
683+
static mut or a global UnsafeCell.");
684+
}
685+
err.emit();
632686
}
633687
}
634688
} else {
@@ -669,9 +723,42 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
669723
(CastTy::FnPtr, CastTy::Int(_)) => {
670724
self.add(Qualif::NOT_CONST);
671725
if self.mode != Mode::Fn {
672-
span_err!(self.tcx.sess, self.span, E0018,
673-
"raw pointers cannot be cast to integers in {}s",
674-
self.mode);
726+
let mut err = struct_span_err!(
727+
self.tcx.sess,
728+
self.span,
729+
E0018,
730+
"raw pointers cannot be cast to integers in {}s",
731+
self.mode
732+
);
733+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
734+
err.note("\
735+
The value of static and constant integers must be known at compile time. You can't cast a pointer \
736+
to an integer because the address of a pointer can vary.
737+
738+
For example, if you write:
739+
740+
```
741+
static MY_STATIC: u32 = 42;
742+
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
743+
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
744+
```
745+
746+
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, the address can change \
747+
when the program is linked, as well as change between different executions due to ASLR, and many \
748+
linkers would not be able to calculate the value of `WHAT`.
749+
750+
On the other hand, static and constant pointers can point either to a known numeric address or to \
751+
the address of a symbol.
752+
753+
```
754+
static MY_STATIC: u32 = 42;
755+
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
756+
const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
757+
```
758+
759+
This does not pose a problem by itself because they can't be accessed directly.");
760+
}
761+
err.emit();
675762
}
676763
}
677764
_ => {}
@@ -702,10 +789,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
702789
Rvalue::NullaryOp(NullOp::Box, _) => {
703790
self.add(Qualif::NOT_CONST);
704791
if self.mode != Mode::Fn {
705-
struct_span_err!(self.tcx.sess, self.span, E0010,
706-
"allocations are not allowed in {}s", self.mode)
707-
.span_label(self.span, format!("allocation not allowed in {}s", self.mode))
708-
.emit();
792+
let mut err = struct_span_err!(self.tcx.sess, self.span, E0010,
793+
"allocations are not allowed in {}s", self.mode);
794+
err.span_label(self.span, format!("allocation not allowed in {}s", self.mode));
795+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
796+
err.note(
797+
"The value of statics and constants must be known at compile time, \
798+
and they live for the entire lifetime of a program. Creating a boxed \
799+
value allocates memory on the heap at runtime, and therefore cannot \
800+
be done at compile time."
801+
);
802+
}
803+
err.emit();
709804
}
710805
}
711806

@@ -931,9 +1026,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
9311026
// Avoid a generic error for other uses of arguments.
9321027
if self.qualif.intersects(Qualif::FN_ARGUMENT) {
9331028
let decl = &self.mir.local_decls[index];
934-
span_err!(self.tcx.sess, decl.source_info.span, E0022,
935-
"arguments of constant functions can only \
936-
be immutable by-value bindings");
1029+
let mut err = struct_span_err!(
1030+
self.tcx.sess,
1031+
decl.source_info.span,
1032+
E0022,
1033+
"arguments of constant functions can only be immutable by-value bindings"
1034+
);
1035+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
1036+
err.note("Constant functions are not allowed to mutate anything. Thus, \
1037+
binding to an argument with a mutable pattern is not allowed.");
1038+
err.note("Remove any mutable bindings from the argument list to fix this \
1039+
error. In case you need to mutate the argument, try lazily \
1040+
initializing a global variable instead of using a const fn, or \
1041+
refactoring the code to a functional style to avoid mutation if \
1042+
possible.");
1043+
}
1044+
err.emit();
9371045
return;
9381046
}
9391047
}

src/librustc_passes/consts.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,20 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
237237
Ok(Ordering::Less) |
238238
Ok(Ordering::Equal) => {}
239239
Ok(Ordering::Greater) => {
240-
struct_span_err!(self.tcx.sess, start.span, E0030,
241-
"lower range bound must be less than or equal to upper")
242-
.span_label(start.span, "lower bound larger than upper bound")
243-
.emit();
240+
let mut err = struct_span_err!(
241+
self.tcx.sess,
242+
start.span,
243+
E0030,
244+
"lower range bound must be less than or equal to upper"
245+
);
246+
err.span_label(start.span, "lower bound larger than upper bound");
247+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
248+
err.note("When matching against a range, the compiler verifies that \
249+
the range is non-empty. Range patterns include both \
250+
end-points, so this is equivalent to requiring the start of \
251+
the range to be less than or equal to the end of the range.");
252+
}
253+
err.emit();
244254
}
245255
Err(ErrorReported) => {}
246256
}

0 commit comments

Comments
 (0)