Auto merge of #68907 - Dylan-DPC:rollup-osm5e8o, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #67359 (Rename -Zexternal-macro-backtrace to -Zmacro-backtrace and clean up implementation.)
 - #68524 (Generator Resume Arguments)
 - #68791 (implement proper linkchecker hardening)
 - #68886 (Mark fn map_or() as eagerly evaluated.)
 - #68888 (error code examples: replace some more ignore with compile_fail)
 - #68894 (Update E0565 examples)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-02-07 00:06:35 +00:00
commit f8fd462447
389 changed files with 2043 additions and 588 deletions

View File

@ -3067,6 +3067,7 @@ name = "rustbook"
version = "0.1.0"
dependencies = [
"clap",
"codespan",
"codespan-reporting",
"failure",
"mdbook",

View File

@ -847,7 +847,13 @@ impl<'a> Builder<'a> {
rustflags.arg("-Zforce-unstable-if-unmarked");
}
rustflags.arg("-Zexternal-macro-backtrace");
// cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace`
// to `-Zmacro-backtrace`, keep only the latter after beta promotion.
if stage == 0 {
rustflags.arg("-Zexternal-macro-backtrace");
} else {
rustflags.arg("-Zmacro-backtrace");
}
let want_rustdoc = self.doc_tests != DocTests::No;

@ -1 +1 @@
Subproject commit 92baf7293dd2d418d2ac4b141b0faa822075d9f7
Subproject commit 5bd60bc51efaec04e69e2e18b59678e2af066433

View File

@ -37,11 +37,11 @@ fn main() {
return "foo"
};
match Pin::new(&mut generator).resume() {
match Pin::new(&mut generator).resume(()) {
GeneratorState::Yielded(1) => {}
_ => panic!("unexpected value from resume"),
}
match Pin::new(&mut generator).resume() {
match Pin::new(&mut generator).resume(()) {
GeneratorState::Complete("foo") => {}
_ => panic!("unexpected value from resume"),
}
@ -71,9 +71,9 @@ fn main() {
};
println!("1");
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume(());
println!("3");
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume(());
println!("5");
}
```
@ -92,10 +92,10 @@ The `Generator` trait in `std::ops` currently looks like:
# use std::ops::GeneratorState;
# use std::pin::Pin;
pub trait Generator {
pub trait Generator<R = ()> {
type Yield;
type Return;
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
}
```
@ -152,10 +152,6 @@ closure-like semantics. Namely:
* Whenever a generator is dropped it will drop all captured environment
variables.
Note that unlike closures, generators at this time cannot take any arguments.
That is, generators must always look like `|| { ... }`. This restriction may be
lifted at a future date, the design is ongoing!
### Generators as state machines
In the compiler, generators are currently compiled as state machines. Each
@ -179,8 +175,8 @@ fn main() {
return ret
};
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume(());
Pin::new(&mut generator).resume(());
}
```
@ -205,7 +201,7 @@ fn main() {
type Yield = i32;
type Return = &'static str;
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<i32, &'static str> {
fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
use std::mem;
match mem::replace(&mut *self, __Generator::Done) {
__Generator::Start(s) => {
@ -228,8 +224,8 @@ fn main() {
__Generator::Start(ret)
};
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume();
Pin::new(&mut generator).resume(());
Pin::new(&mut generator).resume(());
}
```

View File

@ -1104,6 +1104,7 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Box<T> {}
#[cfg(bootstrap)]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
type Yield = G::Yield;
@ -1114,6 +1115,7 @@ impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
}
}
#[cfg(bootstrap)]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
type Yield = G::Yield;
@ -1124,6 +1126,28 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
}
}
#[cfg(not(bootstrap))]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
G::resume(Pin::new(&mut *self), arg)
}
}
#[cfg(not(bootstrap))]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
G::resume((*self).as_mut(), arg)
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
type Output = F::Output;

View File

@ -50,11 +50,11 @@ pub enum GeneratorState<Y, R> {
/// return "foo"
/// };
///
/// match Pin::new(&mut generator).resume() {
/// match Pin::new(&mut generator).resume(()) {
/// GeneratorState::Yielded(1) => {}
/// _ => panic!("unexpected return from resume"),
/// }
/// match Pin::new(&mut generator).resume() {
/// match Pin::new(&mut generator).resume(()) {
/// GeneratorState::Complete("foo") => {}
/// _ => panic!("unexpected return from resume"),
/// }
@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
#[lang = "generator"]
#[unstable(feature = "generator_trait", issue = "43122")]
#[fundamental]
pub trait Generator {
pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
/// The type of value this generator yields.
///
/// This associated type corresponds to the `yield` expression and the
@ -110,9 +110,13 @@ pub trait Generator {
/// been returned previously. While generator literals in the language are
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
/// for all implementations of the `Generator` trait.
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
fn resume(
self: Pin<&mut Self>,
#[cfg(not(bootstrap))] arg: R,
) -> GeneratorState<Self::Yield, Self::Return>;
}
#[cfg(bootstrap)]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
type Yield = G::Yield;
@ -123,6 +127,7 @@ impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
}
}
#[cfg(bootstrap)]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
type Yield = G::Yield;
@ -132,3 +137,25 @@ impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
G::resume(Pin::new(&mut *self))
}
}
#[cfg(not(bootstrap))]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
G::resume((*self).as_mut(), arg)
}
}
#[cfg(not(bootstrap))]
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
G::resume(Pin::new(&mut *self), arg)
}
}

View File

@ -455,6 +455,12 @@ impl<T> Option<T> {
/// Applies a function to the contained value (if any),
/// or returns the provided default (if not).
///
/// Arguments passed to `map_or` are eagerly evaluated; if you are passing
/// the result of a function call, it is recommended to use [`map_or_else`],
/// which is lazily evaluated.
///
/// [`map_or_else`]: #method.map_or_else
///
/// # Examples
///
/// ```

View File

@ -524,6 +524,12 @@ impl<T, E> Result<T, E> {
/// Applies a function to the contained value (if any),
/// or returns the provided default (if not).
///
/// Arguments passed to `map_or` are eagerly evaluated; if you are passing
/// the result of a function call, it is recommended to use [`map_or_else`],
/// which is lazily evaluated.
///
/// [`map_or_else`]: #method.map_or_else
///
/// # Examples
///
/// ```

View File

@ -744,6 +744,7 @@ where
substs.as_generator().return_ty(def_id, self.tcx).visit_with(self);
substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self);
substs.as_generator().resume_ty(def_id, self.tcx).visit_with(self);
}
_ => {
ty.super_visit_with(self);

View File

@ -1120,6 +1120,8 @@ pub enum TerminatorKind<'tcx> {
value: Operand<'tcx>,
/// Where to resume to.
resume: BasicBlock,
/// The place to store the resume argument in.
resume_arg: Place<'tcx>,
/// Cleanup to be done if the generator is dropped at this suspend point.
drop: Option<BasicBlock>,
},
@ -2645,9 +2647,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
target,
unwind,
},
Yield { ref value, resume, drop } => {
Yield { value: value.fold_with(folder), resume: resume, drop: drop }
}
Yield { ref value, resume, ref resume_arg, drop } => Yield {
value: value.fold_with(folder),
resume,
resume_arg: resume_arg.fold_with(folder),
drop,
},
Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
let dest =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));

View File

@ -516,8 +516,14 @@ macro_rules! make_mir_visitor {
TerminatorKind::Yield {
value,
resume: _,
resume_arg,
drop: _,
} => {
self.visit_place(
resume_arg,
PlaceContext::MutatingUse(MutatingUseContext::Store),
source_location,
);
self.visit_operand(value, source_location);
}

View File

@ -643,8 +643,10 @@ pub fn generator_trait_ref_and_outputs(
self_ty: Ty<'tcx>,
sig: ty::PolyGenSig<'tcx>,
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
let trait_ref =
ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
let trait_ref = ty::TraitRef {
def_id: fn_trait_def_id,
substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
};
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
}

View File

@ -2350,8 +2350,9 @@ impl<'tcx> ty::Instance<'tcx> {
]);
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
tcx.mk_fn_sig(iter::once(env_ty),
ret_ty,
tcx.mk_fn_sig(
[env_ty, sig.resume_ty].iter(),
&ret_ty,
false,
hir::Unsafety::Normal,
rustc_target::spec::abi::Abi::Rust

View File

@ -598,8 +598,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::GenSig<'a> {
type Lifted = ty::GenSig<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(&(self.yield_ty, self.return_ty))
.map(|(yield_ty, return_ty)| ty::GenSig { yield_ty, return_ty })
tcx.lift(&(self.resume_ty, self.yield_ty, self.return_ty))
.map(|(resume_ty, yield_ty, return_ty)| ty::GenSig { resume_ty, yield_ty, return_ty })
}
}

View File

@ -346,9 +346,17 @@ static_assert_size!(TyKind<'_>, 24);
/// ## Generators
///
/// Generators are handled similarly in `GeneratorSubsts`. The set of
/// type parameters is similar, but the role of CK and CS are
/// different. CK represents the "yield type" and CS represents the
/// "return type" of the generator.
/// type parameters is similar, but `CK` and `CS` are replaced by the
/// following type parameters:
///
/// * `GS`: The generator's "resume type", which is the type of the
/// argument passed to `resume`, and the type of `yield` expressions
/// inside the generator.
/// * `GY`: The "yield type", which is the type of values passed to
/// `yield` inside the generator.
/// * `GR`: The "return type", which is the type of value returned upon
/// completion of the generator.
/// * `GW`: The "generator witness".
#[derive(Copy, Clone, Debug, TypeFoldable)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
@ -442,6 +450,7 @@ pub struct GeneratorSubsts<'tcx> {
}
struct SplitGeneratorSubsts<'tcx> {
resume_ty: Ty<'tcx>,
yield_ty: Ty<'tcx>,
return_ty: Ty<'tcx>,
witness: Ty<'tcx>,
@ -453,10 +462,11 @@ impl<'tcx> GeneratorSubsts<'tcx> {
let generics = tcx.generics_of(def_id);
let parent_len = generics.parent_count;
SplitGeneratorSubsts {
yield_ty: self.substs.type_at(parent_len),
return_ty: self.substs.type_at(parent_len + 1),
witness: self.substs.type_at(parent_len + 2),
upvar_kinds: &self.substs[parent_len + 3..],
resume_ty: self.substs.type_at(parent_len),
yield_ty: self.substs.type_at(parent_len + 1),
return_ty: self.substs.type_at(parent_len + 2),
witness: self.substs.type_at(parent_len + 3),
upvar_kinds: &self.substs[parent_len + 4..],
}
}
@ -485,6 +495,11 @@ impl<'tcx> GeneratorSubsts<'tcx> {
})
}
/// Returns the type representing the resume type of the generator.
pub fn resume_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).resume_ty
}
/// Returns the type representing the yield type of the generator.
pub fn yield_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).yield_ty
@ -505,10 +520,14 @@ impl<'tcx> GeneratorSubsts<'tcx> {
ty::Binder::dummy(self.sig(def_id, tcx))
}
/// Returns the "generator signature", which consists of its yield
/// Returns the "generator signature", which consists of its resume, yield
/// and return types.
pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> GenSig<'tcx> {
ty::GenSig { yield_ty: self.yield_ty(def_id, tcx), return_ty: self.return_ty(def_id, tcx) }
ty::GenSig {
resume_ty: self.resume_ty(def_id, tcx),
yield_ty: self.yield_ty(def_id, tcx),
return_ty: self.return_ty(def_id, tcx),
}
}
}
@ -1072,6 +1091,7 @@ impl<'tcx> ProjectionTy<'tcx> {
#[derive(Clone, Debug, TypeFoldable)]
pub struct GenSig<'tcx> {
pub resume_ty: Ty<'tcx>,
pub yield_ty: Ty<'tcx>,
pub return_ty: Ty<'tcx>,
}
@ -1079,6 +1099,9 @@ pub struct GenSig<'tcx> {
pub type PolyGenSig<'tcx> = Binder<GenSig<'tcx>>;
impl<'tcx> PolyGenSig<'tcx> {
pub fn resume_ty(&self) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|sig| sig.resume_ty)
}
pub fn yield_ty(&self) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|sig| sig.yield_ty)
}

View File

@ -688,12 +688,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> Option<hir::Movability> {
match generator_kind {
Some(hir::GeneratorKind::Gen) => {
if !decl.inputs.is_empty() {
if decl.inputs.len() > 1 {
struct_span_err!(
self.sess,
fn_decl_span,
E0628,
"generators cannot have explicit parameters"
"too many parameters for a generator (expected 0 or 1 parameters)"
)
.emit();
}

View File

@ -25,6 +25,7 @@ pub struct PinnedGenerator<I, A, R> {
}
impl<I, A, R> PinnedGenerator<I, A, R> {
#[cfg(bootstrap)]
pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
generator: T,
) -> (I, Self) {
@ -39,6 +40,22 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
(init, result)
}
#[cfg(not(bootstrap))]
pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
generator: T,
) -> (I, Self) {
let mut result = PinnedGenerator { generator: Box::pin(generator) };
// Run it to the first yield to set it up
let init = match Pin::new(&mut result.generator).resume(()) {
GeneratorState::Yielded(YieldType::Initial(y)) => y,
_ => panic!(),
};
(init, result)
}
#[cfg(bootstrap)]
pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
BOX_REGION_ARG.with(|i| {
i.set(Action::Access(AccessAction(closure)));
@ -50,6 +67,19 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
}
}
#[cfg(not(bootstrap))]
pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
BOX_REGION_ARG.with(|i| {
i.set(Action::Access(AccessAction(closure)));
});
// Call the generator, which in turn will call the closure in BOX_REGION_ARG
if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume(()) {
panic!()
}
}
#[cfg(bootstrap)]
pub fn complete(&mut self) -> R {
// Tell the generator we want it to complete, consuming it and yielding a result
BOX_REGION_ARG.with(|i| i.set(Action::Complete));
@ -57,6 +87,15 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
let result = Pin::new(&mut self.generator).resume();
if let GeneratorState::Complete(r) = result { r } else { panic!() }
}
#[cfg(not(bootstrap))]
pub fn complete(&mut self) -> R {
// Tell the generator we want it to complete, consuming it and yielding a result
BOX_REGION_ARG.with(|i| i.set(Action::Complete));
let result = Pin::new(&mut self.generator).resume(());
if let GeneratorState::Complete(r) = result { r } else { panic!() }
}
}
#[derive(PartialEq)]

View File

@ -1,7 +1,7 @@
Invalid monomorphization of an intrinsic function was used. Erroneous code
example:
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
```compile_fail,E0511
#![feature(platform_intrinsics)]
extern "platform-intrinsic" {

View File

@ -2,7 +2,7 @@ The `inline` attribute was malformed.
Erroneous code example:
```ignore (compile_fail not working here; see Issue #43707)
```compile_fail,E0534
#[inline()] // error: expected one argument
pub fn something() {}

View File

@ -2,7 +2,7 @@ An unknown argument was given to the `inline` attribute.
Erroneous code example:
```ignore (compile_fail not working here; see Issue #43707)
```compile_fail,E0535
#[inline(unknown)] // error: invalid argument
pub fn something() {}

View File

@ -2,9 +2,11 @@ A literal was used in a built-in attribute that doesn't support literals.
Erroneous code example:
```ignore (compile_fail not working here; see Issue #43707)
#[inline("always")] // error: unsupported literal
pub fn something() {}
```compile_fail,E0565
#[repr("C")] // error: meta item in `repr` must be an identifier
struct Repr {}
fn main() {}
```
Literals in attributes are new and largely unsupported in built-in attributes.
@ -12,6 +14,8 @@ Work to support literals where appropriate is ongoing. Try using an unquoted
name instead:
```
#[inline(always)]
pub fn something() {}
#[repr(C)] // ok!
struct Repr {}
fn main() {}
```

View File

@ -12,7 +12,7 @@ let mut b = || {
yield (); // ...is still in scope here, when the yield occurs.
println!("{}", a);
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
```
At present, it is not permitted to have a yield that occurs while a
@ -31,7 +31,7 @@ let mut b = || {
yield ();
println!("{}", a);
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
```
This is a very simple case, of course. In more complex cases, we may
@ -50,7 +50,7 @@ let mut b = || {
yield x; // ...when this yield occurs.
}
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
```
Such cases can sometimes be resolved by iterating "by value" (or using
@ -66,7 +66,7 @@ let mut b = || {
yield x; // <-- Now yield is OK.
}
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
```
If taking ownership is not an option, using indices can work too:
@ -83,7 +83,7 @@ let mut b = || {
yield x; // <-- Now yield is OK.
}
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
// (*) -- Unfortunately, these temporaries are currently required.
// See <https://github.com/rust-lang/rust/issues/43122>.

View File

@ -2,7 +2,9 @@ The `unwind` attribute was malformed.
Erroneous code example:
```ignore (compile_fail not working here; see Issue #43707)
```compile_fail,E0633
#![feature(unwind_attributes)]
#[unwind()] // error: expected one argument
pub extern fn something() {}

View File

@ -6,7 +6,7 @@ assembly call.
In particular, it can happen if you forgot the closing bracket of a register
constraint (see issue #51430):
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
```compile_fail,E0668
#![feature(asm)]
fn main() {

View File

@ -23,7 +23,7 @@ pub struct AnnotateSnippetEmitterWriter {
/// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs.
ui_testing: bool,
external_macro_backtrace: bool,
macro_backtrace: bool,
}
impl Emitter for AnnotateSnippetEmitterWriter {
@ -32,12 +32,12 @@ impl Emitter for AnnotateSnippetEmitterWriter {
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
self.fix_multispans_in_std_macros(
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
&self.source_map,
&mut primary_span,
&mut children,
&diag.level,
self.external_macro_backtrace,
self.macro_backtrace,
);
self.emit_messages_default(
@ -172,9 +172,9 @@ impl AnnotateSnippetEmitterWriter {
pub fn new(
source_map: Option<Lrc<SourceMap>>,
short_message: bool,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> Self {
Self { source_map, short_message, ui_testing: false, external_macro_backtrace }
Self { source_map, short_message, ui_testing: false, macro_backtrace }
}
/// Allows to modify `Self` to enable or disable the `ui_testing` flag.

View File

@ -14,7 +14,6 @@ use rustc_span::{MultiSpan, SourceFile, Span};
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
use crate::styled_buffer::StyledBuffer;
use crate::Level::Error;
use crate::{
pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
};
@ -27,6 +26,7 @@ use std::borrow::Cow;
use std::cmp::{max, min, Reverse};
use std::io;
use std::io::prelude::*;
use std::iter;
use std::path::Path;
use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream};
use termcolor::{Buffer, Color, WriteColor};
@ -54,19 +54,11 @@ impl HumanReadableErrorType {
source_map: Option<Lrc<SourceMap>>,
teach: bool,
terminal_width: Option<usize>,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> EmitterWriter {
let (short, color_config) = self.unzip();
let color = color_config.suggests_using_colors();
EmitterWriter::new(
dst,
source_map,
short,
teach,
color,
terminal_width,
external_macro_backtrace,
)
EmitterWriter::new(dst, source_map, short, teach, color, terminal_width, macro_backtrace)
}
}
@ -280,10 +272,7 @@ pub trait Emitter {
}
}
// This does a small "fix" for multispans by looking to see if it can find any that
// point directly at <*macros>. Since these are often difficult to read, this
// will change the span to point at the use site.
fn fix_multispans_in_std_macros(
fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
&self,
source_map: &Option<Lrc<SourceMap>>,
span: &mut MultiSpan,
@ -291,127 +280,187 @@ pub trait Emitter {
level: &Level,
backtrace: bool,
) {
let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
for child in children.iter_mut() {
spans_updated |=
self.fix_multispan_in_std_macros(source_map, &mut child.span, backtrace);
}
let msg = if level == &Error {
"this error originates in a macro outside of the current crate \
(in Nightly builds, run with -Z external-macro-backtrace \
for more info)"
.to_string()
} else {
"this warning originates in a macro outside of the current crate \
(in Nightly builds, run with -Z external-macro-backtrace \
for more info)"
.to_string()
};
// Check for spans in macros, before `fix_multispans_in_extern_macros`
// has a chance to replace them.
let has_macro_spans = iter::once(&*span)
.chain(children.iter().map(|child| &child.span))
.flat_map(|span| span.primary_spans())
.copied()
.flat_map(|sp| {
sp.macro_backtrace().filter_map(|expn_data| {
match expn_data.kind {
ExpnKind::Root => None,
if spans_updated {
children.push(SubDiagnostic {
level: Level::Note,
message: vec![(msg, Style::NoStyle)],
span: MultiSpan::new(),
render_span: None,
});
// Skip past non-macro entries, just in case there
// are some which do actually involve macros.
ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
ExpnKind::Macro(macro_kind, _) => Some(macro_kind),
}
})
})
.next();
if !backtrace {
self.fix_multispans_in_extern_macros(source_map, span, children);
}
self.render_multispans_macro_backtrace(span, children, backtrace);
if !backtrace {
if let Some(macro_kind) = has_macro_spans {
let msg = format!(
"this {} originates in {} {} \
(in Nightly builds, run with -Z macro-backtrace for more info)",
level,
macro_kind.article(),
macro_kind.descr(),
);
children.push(SubDiagnostic {
level: Level::Note,
message: vec![(msg, Style::NoStyle)],
span: MultiSpan::new(),
render_span: None,
});
}
}
}
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
// <*macros>. Since these locations are often difficult to read, we move these Spans from
// <*macros> to their corresponding use site.
fn fix_multispan_in_std_macros(
fn render_multispans_macro_backtrace(
&self,
source_map: &Option<Lrc<SourceMap>>,
span: &mut MultiSpan,
always_backtrace: bool,
) -> bool {
let sm = match source_map {
Some(ref sm) => sm,
None => return false,
};
children: &mut Vec<SubDiagnostic>,
backtrace: bool,
) {
for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) {
self.render_multispan_macro_backtrace(span, backtrace);
}
}
let mut before_after: Vec<(Span, Span)> = vec![];
fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrace: bool) {
let mut new_labels: Vec<(Span, String)> = vec![];
// First, find all the spans in <*macros> and point instead at their use site
for sp in span.primary_spans() {
for &sp in span.primary_spans() {
if sp.is_dummy() {
continue;
}
let call_sp = sm.call_span_if_macro(*sp);
if call_sp != *sp && !always_backtrace {
before_after.push((*sp, call_sp));
}
// FIXME(eddyb) use `retain` on `macro_backtrace` to remove all the
// entries we don't want to print, to make sure the indices being
// printed are contiguous (or omitted if there's only one entry).
let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
let backtrace_len = macro_backtrace.len();
for (i, trace) in macro_backtrace.iter().rev().enumerate() {
// Only show macro locations that are local
// and display them like a span_note
if trace.def_site.is_dummy() {
continue;
}
if always_backtrace {
new_labels.push((
trace.def_site,
format!(
"in this expansion of `{}`{}",
trace.kind.descr(),
if backtrace_len > 2 {
// if backtrace_len == 1 it'll be pointed
// at by "in this macro invocation"
if macro_backtrace.len() > 2 {
// if macro_backtrace.len() == 1 it'll be
// pointed at by "in this macro invocation"
format!(" (#{})", i + 1)
} else {
String::new()
}
},
),
));
}
// Check to make sure we're not in any <*macros>
if !sm.span_to_filename(trace.def_site).is_macros()
&& matches!(trace.kind, ExpnKind::Macro(MacroKind::Bang, _))
// Don't add a label on the call site if the diagnostic itself
// already points to (a part of) that call site, as the label
// is meant for showing the relevant invocation when the actual
// diagnostic is pointing to some part of macro definition.
//
// This also handles the case where an external span got replaced
// with the call site span by `fix_multispans_in_extern_macros`.
//
// NB: `-Zmacro-backtrace` overrides this, for uniformity, as the
// "in this expansion of" label above is always added in that mode,
// and it needs an "in this macro invocation" label to match that.
let redundant_span = trace.call_site.contains(sp);
if !redundant_span && matches!(trace.kind, ExpnKind::Macro(MacroKind::Bang, _))
|| always_backtrace
{
new_labels.push((
trace.call_site,
format!(
"in this macro invocation{}",
if backtrace_len > 2 && always_backtrace {
if macro_backtrace.len() > 2 && always_backtrace {
// only specify order when the macro
// backtrace is multiple levels deep
format!(" (#{})", i + 1)
} else {
String::new()
}
},
),
));
if !always_backtrace {
break;
}
}
if !always_backtrace {
break;
}
}
}
for (label_span, label_text) in new_labels {
span.push_span_label(label_span, label_text);
}
for sp_label in span.span_labels() {
if sp_label.span.is_dummy() {
continue;
}
if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace {
if let Some(use_site) = sp_label.span.macro_backtrace().last() {
before_after.push((sp_label.span, use_site.call_site));
}
}
}
// After we have them, make sure we replace these 'bad' def sites with their use sites
let spans_updated = !before_after.is_empty();
for (before, after) in before_after {
span.replace(before, after);
}
}
spans_updated
// This does a small "fix" for multispans by looking to see if it can find any that
// point directly at <*macros>. Since these are often difficult to read, this
// will change the span to point at the use site.
fn fix_multispans_in_extern_macros(
&self,
source_map: &Option<Lrc<SourceMap>>,
span: &mut MultiSpan,
children: &mut Vec<SubDiagnostic>,
) {
for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) {
self.fix_multispan_in_extern_macros(source_map, span);
}
}
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
// <*macros>. Since these locations are often difficult to read, we move these Spans from
// <*macros> to their corresponding use site.
fn fix_multispan_in_extern_macros(
&self,
source_map: &Option<Lrc<SourceMap>>,
span: &mut MultiSpan,
) {
let sm = match source_map {
Some(ref sm) => sm,
None => return,
};
// First, find all the spans in <*macros> and point instead at their use site
let replacements: Vec<(Span, Span)> = span
.primary_spans()
.iter()
.copied()
.chain(span.span_labels().iter().map(|sp_label| sp_label.span))
.filter_map(|sp| {
if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() {
let maybe_callsite = sp.source_callsite();
if sp != maybe_callsite {
return Some((sp, maybe_callsite));
}
}
None
})
.collect();
// After we have them, make sure we replace these 'bad' def sites with their use sites
for (from, to) in replacements {
span.replace(from, to);
}
}
}
@ -424,12 +473,12 @@ impl Emitter for EmitterWriter {
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
self.fix_multispans_in_std_macros(
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
&self.sm,
&mut primary_span,
&mut children,
&diag.level,
self.external_macro_backtrace,
self.macro_backtrace,
);
self.emit_messages_default(
@ -508,7 +557,7 @@ pub struct EmitterWriter {
ui_testing: bool,
terminal_width: Option<usize>,
external_macro_backtrace: bool,
macro_backtrace: bool,
}
#[derive(Debug)]
@ -525,7 +574,7 @@ impl EmitterWriter {
short_message: bool,
teach: bool,
terminal_width: Option<usize>,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> EmitterWriter {
let dst = Destination::from_stderr(color_config);
EmitterWriter {
@ -535,7 +584,7 @@ impl EmitterWriter {
teach,
ui_testing: false,
terminal_width,
external_macro_backtrace,
macro_backtrace,
}
}
@ -546,7 +595,7 @@ impl EmitterWriter {
teach: bool,
colored: bool,
terminal_width: Option<usize>,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> EmitterWriter {
EmitterWriter {
dst: Raw(dst, colored),
@ -555,7 +604,7 @@ impl EmitterWriter {
teach,
ui_testing: false,
terminal_width,
external_macro_backtrace,
macro_backtrace,
}
}

View File

@ -36,7 +36,7 @@ pub struct JsonEmitter {
pretty: bool,
ui_testing: bool,
json_rendered: HumanReadableErrorType,
external_macro_backtrace: bool,
macro_backtrace: bool,
}
impl JsonEmitter {
@ -45,7 +45,7 @@ impl JsonEmitter {
source_map: Lrc<SourceMap>,
pretty: bool,
json_rendered: HumanReadableErrorType,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> JsonEmitter {
JsonEmitter {
dst: Box::new(io::stderr()),
@ -54,14 +54,14 @@ impl JsonEmitter {
pretty,
ui_testing: false,
json_rendered,
external_macro_backtrace,
macro_backtrace,
}
}
pub fn basic(
pretty: bool,
json_rendered: HumanReadableErrorType,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
JsonEmitter::stderr(
@ -69,7 +69,7 @@ impl JsonEmitter {
Lrc::new(SourceMap::new(file_path_mapping)),
pretty,
json_rendered,
external_macro_backtrace,
macro_backtrace,
)
}
@ -79,7 +79,7 @@ impl JsonEmitter {
source_map: Lrc<SourceMap>,
pretty: bool,
json_rendered: HumanReadableErrorType,
external_macro_backtrace: bool,
macro_backtrace: bool,
) -> JsonEmitter {
JsonEmitter {
dst,
@ -88,7 +88,7 @@ impl JsonEmitter {
pretty,
ui_testing: false,
json_rendered,
external_macro_backtrace,
macro_backtrace,
}
}
@ -245,13 +245,7 @@ impl Diagnostic {
let buf = BufWriter::default();
let output = buf.clone();
je.json_rendered
.new_emitter(
Box::new(buf),
Some(je.sm.clone()),
false,
None,
je.external_macro_backtrace,
)
.new_emitter(Box::new(buf), Some(je.sm.clone()), false, None, je.macro_backtrace)
.ui_testing(je.ui_testing)
.emit_diagnostic(diag);
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();

View File

@ -336,9 +336,9 @@ pub struct HandlerFlags {
/// If true, immediately print bugs registered with `delay_span_bug`.
/// (rustc: see `-Z report-delayed-bugs`)
pub report_delayed_bugs: bool,
/// show macro backtraces even for non-local macros.
/// (rustc: see `-Z external-macro-backtrace`)
pub external_macro_backtrace: bool,
/// Show macro backtraces.
/// (rustc: see `-Z macro-backtrace`)
pub macro_backtrace: bool,
/// If true, identical diagnostics are reported only once.
pub deduplicate_diagnostics: bool,
}
@ -385,7 +385,7 @@ impl Handler {
false,
false,
None,
flags.external_macro_backtrace,
flags.macro_backtrace,
));
Self::with_emitter_and_flags(emitter, flags)
}

View File

@ -159,7 +159,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.consume_operand(location, index);
}
}
TerminatorKind::Yield { ref value, resume, drop: _ } => {
TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
self.consume_operand(location, value);
// Invalidate all borrows of local places
@ -170,6 +170,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.all_facts.invalidates.push((resume, i));
}
}
self.mutate_place(location, resume_arg, Deep, JustWrite);
}
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
// Invalidate all borrows of local places

View File

@ -684,7 +684,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
}
}
TerminatorKind::Yield { ref value, resume: _, drop: _ } => {
TerminatorKind::Yield { ref value, resume: _, ref resume_arg, drop: _ } => {
self.consume_operand(loc, (value, span), flow_state);
if self.movable_generator {
@ -697,6 +697,8 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
}
});
}
self.mutate_place(loc, (resume_arg, span), Deep, JustWrite, flow_state);
}
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {

View File

@ -581,9 +581,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
DefiningTy::Generator(def_id, substs, movability) => {
assert_eq!(self.mir_def_id, def_id);
let resume_ty = substs.as_generator().resume_ty(def_id, tcx);
let output = substs.as_generator().return_ty(def_id, tcx);
let generator_ty = tcx.mk_generator(def_id, substs, movability);
let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]);
let inputs_and_output =
self.infcx.tcx.intern_type_list(&[generator_ty, resume_ty, output]);
ty::Binder::dummy(inputs_and_output)
}

View File

@ -31,10 +31,12 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
self.body.local_decls.len()
}
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
// Nothing is live on function entry (generators only have a self
// argument, and we don't care about that)
assert_eq!(1, self.body.arg_count);
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
// The resume argument is live on function entry (we don't care about
// the `self` argument)
for arg in self.body.args_iter().skip(1) {
on_entry.insert(arg);
}
}
fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
@ -100,10 +102,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
self.body.local_decls.len()
}
fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
// Nothing is live on function entry (generators only have a self
// argument, and we don't care about that)
assert_eq!(1, self.body.arg_count);
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
// The resume argument is live on function entry (we don't care about
// the `self` argument)
for arg in self.body.args_iter().skip(1) {
on_entry.insert(arg);
}
}
fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {

View File

@ -380,7 +380,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
self.gather_operand(discr);
}
TerminatorKind::Yield { ref value, .. } => {
TerminatorKind::Yield { ref value, resume_arg: ref place, .. } => {
self.create_move_path(place);
self.gather_init(place.as_ref(), InitKind::Deep);
self.gather_operand(value);
}

View File

@ -192,9 +192,10 @@ const RETURNED: usize = GeneratorSubsts::RETURNED;
/// Generator has been poisoned
const POISONED: usize = GeneratorSubsts::POISONED;
struct SuspensionPoint {
struct SuspensionPoint<'tcx> {
state: usize,
resume: BasicBlock,
resume_arg: Place<'tcx>,
drop: Option<BasicBlock>,
storage_liveness: liveness::LiveVarSet,
}
@ -216,7 +217,7 @@ struct TransformVisitor<'tcx> {
storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>,
// A list of suspension points, generated during the transform
suspension_points: Vec<SuspensionPoint>,
suspension_points: Vec<SuspensionPoint<'tcx>>,
// The original RETURN_PLACE local
new_ret_local: Local,
@ -303,8 +304,8 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
Operand::Move(Place::from(self.new_ret_local)),
None,
)),
TerminatorKind::Yield { ref value, resume, drop } => {
Some((VariantIdx::new(0), Some(resume), value.clone(), drop))
TerminatorKind::Yield { ref value, resume, resume_arg, drop } => {
Some((VariantIdx::new(0), Some((resume, resume_arg)), value.clone(), drop))
}
_ => None,
};
@ -319,13 +320,14 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
self.make_state(state_idx, v),
)),
});
let state = if let Some(resume) = resume {
let state = if let Some((resume, resume_arg)) = resume {
// Yield
let state = 3 + self.suspension_points.len();
self.suspension_points.push(SuspensionPoint {
state,
resume,
resume_arg,
drop,
storage_liveness: self.storage_liveness.get(&block).unwrap().clone(),
});
@ -378,28 +380,35 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
PinArgVisitor { ref_gen_ty, tcx }.visit_body(body);
}
fn replace_result_variable<'tcx>(
ret_ty: Ty<'tcx>,
/// Allocates a new local and replaces all references of `local` with it. Returns the new local.
///
/// `local` will be changed to a new local decl with type `ty`.
///
/// Note that the new local will be uninitialized. It is the caller's responsibility to assign some
/// valid value to it before its first use.
fn replace_local<'tcx>(
local: Local,
ty: Ty<'tcx>,
body: &mut BodyAndCache<'tcx>,
tcx: TyCtxt<'tcx>,
) -> Local {
let source_info = source_info(body);
let new_ret = LocalDecl {
let new_decl = LocalDecl {
mutability: Mutability::Mut,
ty: ret_ty,
ty,
user_ty: UserTypeProjections::none(),
source_info,
internal: false,
is_block_tail: None,
local_info: LocalInfo::Other,
};
let new_ret_local = Local::new(body.local_decls.len());
body.local_decls.push(new_ret);
body.local_decls.swap(RETURN_PLACE, new_ret_local);
let new_local = Local::new(body.local_decls.len());
body.local_decls.push(new_decl);
body.local_decls.swap(local, new_local);
RenameLocalVisitor { from: RETURN_PLACE, to: new_ret_local, tcx }.visit_body(body);
RenameLocalVisitor { from: local, to: new_local, tcx }.visit_body(body);
new_ret_local
new_local
}
struct StorageIgnored(liveness::LiveVarSet);
@ -792,6 +801,10 @@ fn compute_layout<'tcx>(
(remap, layout, storage_liveness)
}
/// Replaces the entry point of `body` with a block that switches on the generator discriminant and
/// dispatches to blocks according to `cases`.
///
/// After this function, the former entry point of the function will be bb1.
fn insert_switch<'tcx>(
body: &mut BodyAndCache<'tcx>,
cases: Vec<(usize, BasicBlock)>,
@ -885,10 +898,11 @@ fn create_generator_drop_shim<'tcx>(
drop_clean: BasicBlock,
) -> BodyAndCache<'tcx> {
let mut body = body.clone();
body.arg_count = 1; // make sure the resume argument is not included here
let source_info = source_info(&body);
let mut cases = create_cases(&mut body, transform, |point| point.drop);
let mut cases = create_cases(&mut body, transform, Operation::Drop);
cases.insert(0, (UNRESUMED, drop_clean));
@ -1006,7 +1020,7 @@ fn create_generator_resume_function<'tcx>(
}
}
let mut cases = create_cases(body, &transform, |point| Some(point.resume));
let mut cases = create_cases(body, &transform, Operation::Resume);
use rustc::mir::interpret::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn};
@ -1056,14 +1070,27 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock {
drop_clean
}
fn create_cases<'tcx, F>(
/// An operation that can be performed on a generator.
#[derive(PartialEq, Copy, Clone)]
enum Operation {
Resume,
Drop,
}
impl Operation {
fn target_block(self, point: &SuspensionPoint<'_>) -> Option<BasicBlock> {
match self {
Operation::Resume => Some(point.resume),
Operation::Drop => point.drop,
}
}
}
fn create_cases<'tcx>(
body: &mut BodyAndCache<'tcx>,
transform: &TransformVisitor<'tcx>,
target: F,
) -> Vec<(usize, BasicBlock)>
where
F: Fn(&SuspensionPoint) -> Option<BasicBlock>,
{
operation: Operation,
) -> Vec<(usize, BasicBlock)> {
let source_info = source_info(body);
transform
@ -1071,12 +1098,19 @@ where
.iter()
.filter_map(|point| {
// Find the target for this suspension point, if applicable
target(point).map(|target| {
operation.target_block(point).map(|target| {
let block = BasicBlock::new(body.basic_blocks().len());
let mut statements = Vec::new();
// Create StorageLive instructions for locals with live storage
for i in 0..(body.local_decls.len()) {
if i == 2 {
// The resume argument is live on function entry. Don't insert a
// `StorageLive`, or the following `Assign` will read from uninitialized
// memory.
continue;
}
let l = Local::new(i);
if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) {
statements
@ -1084,6 +1118,18 @@ where
}
}
if operation == Operation::Resume {
// Move the resume argument to the destination place of the `Yield` terminator
let resume_arg = Local::new(2); // 0 = return, 1 = self
statements.push(Statement {
source_info,
kind: StatementKind::Assign(box (
point.resume_arg,
Rvalue::Use(Operand::Move(resume_arg.into())),
)),
});
}
// Then jump to the real target
body.basic_blocks_mut().push(BasicBlockData {
statements,
@ -1138,7 +1184,29 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
// RETURN_PLACE then is a fresh unused local with type ret_ty.
let new_ret_local = replace_result_variable(ret_ty, body, tcx);
let new_ret_local = replace_local(RETURN_PLACE, ret_ty, body, tcx);
// We also replace the resume argument and insert an `Assign`.
// This is needed because the resume argument `_2` might be live across a `yield`, in which
// case there is no `Assign` to it that the transform can turn into a store to the generator
// state. After the yield the slot in the generator state would then be uninitialized.
let resume_local = Local::new(2);
let new_resume_local =
replace_local(resume_local, body.local_decls[resume_local].ty, body, tcx);
// When first entering the generator, move the resume argument into its new local.
let source_info = source_info(body);
let stmts = &mut body.basic_blocks_mut()[BasicBlock::new(0)].statements;
stmts.insert(
0,
Statement {
source_info,
kind: StatementKind::Assign(box (
new_resume_local.into(),
Rvalue::Use(Operand::Move(resume_local.into())),
)),
},
);
// Extract locals which are live across suspension point into `layout`
// `remap` gives a mapping from local indices onto generator struct indices
@ -1162,9 +1230,9 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
};
transform.visit_body(body);
// Update our MIR struct to reflect the changed we've made
// Update our MIR struct to reflect the changes we've made
body.yield_ty = None;
body.arg_count = 1;
body.arg_count = 2; // self, resume arg
body.spread_arg = None;
body.generator_layout = Some(layout);

View File

@ -230,18 +230,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block = unpack!(this.stmt_expr(block, expr, None));
block.and(this.unit_rvalue())
}
ExprKind::Yield { value } => {
let value = unpack!(block = this.as_operand(block, scope, value));
let resume = this.cfg.start_new_block();
let cleanup = this.generator_drop_cleanup();
this.cfg.terminate(
block,
source_info,
TerminatorKind::Yield { value: value, resume: resume, drop: cleanup },
);
resume.and(this.unit_rvalue())
}
ExprKind::Literal { .. }
ExprKind::Yield { .. }
| ExprKind::Literal { .. }
| ExprKind::StaticRef { .. }
| ExprKind::Block { .. }
| ExprKind::Match { .. }

View File

@ -50,6 +50,7 @@ impl Category {
| ExprKind::Adt { .. }
| ExprKind::Borrow { .. }
| ExprKind::AddressOf { .. }
| ExprKind::Yield { .. }
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
ExprKind::Array { .. }
@ -63,7 +64,6 @@ impl Category {
| ExprKind::Repeat { .. }
| ExprKind::Assign { .. }
| ExprKind::AssignOp { .. }
| ExprKind::Yield { .. }
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant),

View File

@ -365,6 +365,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.unit()
}
ExprKind::Yield { value } => {
let scope = this.local_scope();
let value = unpack!(block = this.as_operand(block, scope, value));
let resume = this.cfg.start_new_block();
let cleanup = this.generator_drop_cleanup();
this.cfg.terminate(
block,
source_info,
TerminatorKind::Yield {
value,
resume,
resume_arg: destination.clone(),
drop: cleanup,
},
);
resume.unit()
}
// these are the cases that are more naturally handled by some other mode
ExprKind::Unary { .. }
| ExprKind::Binary { .. }
@ -376,8 +394,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Tuple { .. }
| ExprKind::Closure { .. }
| ExprKind::Literal { .. }
| ExprKind::StaticRef { .. }
| ExprKind::Yield { .. } => {
| ExprKind::StaticRef { .. } => {
debug_assert!(match Category::of(&expr.kind).unwrap() {
// should be handled above
Category::Rvalue(RvalueFunc::Into) => false,

View File

@ -68,6 +68,12 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let fn_sig = cx.tables().liberated_fn_sigs()[id];
let fn_def_id = tcx.hir().local_def_id(id);
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe => Safety::FnUnsafe,
};
let body = tcx.hir().body(body_id);
let ty = tcx.type_of(fn_def_id);
let mut abi = fn_sig.abi;
let implicit_argument = match ty.kind {
@ -75,21 +81,25 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
abi = Abi::Rust;
Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
}
ty::Generator(..) => {
let gen_ty = tcx.body_tables(body_id).node_type(id);
Some(ArgInfo(gen_ty, None, None, None))
// The resume argument may be missing, in that case we need to provide it here.
// It will always be `()` in this case.
if body.params.is_empty() {
vec![
ArgInfo(gen_ty, None, None, None),
ArgInfo(tcx.mk_unit(), None, None, None),
]
} else {
vec![ArgInfo(gen_ty, None, None, None)]
}
}
_ => None,
_ => vec![],
};
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe => Safety::FnUnsafe,
};
let body = tcx.hir().body(body_id);
let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
let owner_id = tcx.hir().body_owner(body_id);
let opt_ty_info;

View File

@ -624,7 +624,7 @@ impl DebuggingOptions {
treat_err_as_bug: self.treat_err_as_bug,
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
report_delayed_bugs: self.report_delayed_bugs,
external_macro_backtrace: self.external_macro_backtrace,
macro_backtrace: self.macro_backtrace,
deduplicate_diagnostics: self.deduplicate_diagnostics.unwrap_or(true),
}
}

View File

@ -776,8 +776,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"treat error number `val` that occurs as bug"),
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
"immediately print bugs registered with `delay_span_bug`"),
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces even for non-local macros"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces"),
teach: bool = (false, parse_bool, [TRACKED],
"show extended diagnostic help"),
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],

View File

@ -858,7 +858,7 @@ fn default_emitter(
source_map: &Lrc<source_map::SourceMap>,
emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
let macro_backtrace = sopts.debugging_opts.macro_backtrace;
match (sopts.error_format, emitter_dest) {
(config::ErrorOutputType::HumanReadable(kind), dst) => {
let (short, color_config) = kind.unzip();
@ -867,7 +867,7 @@ fn default_emitter(
let emitter = AnnotateSnippetEmitterWriter::new(
Some(source_map.clone()),
short,
external_macro_backtrace,
macro_backtrace,
);
Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing()))
} else {
@ -878,7 +878,7 @@ fn default_emitter(
short,
sopts.debugging_opts.teach,
sopts.debugging_opts.terminal_width,
external_macro_backtrace,
macro_backtrace,
),
Some(dst) => EmitterWriter::new(
dst,
@ -887,7 +887,7 @@ fn default_emitter(
false, // no teach messages when writing to a buffer
false, // no colors when writing to a buffer
None, // no terminal width
external_macro_backtrace,
macro_backtrace,
),
};
Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing()))
@ -899,7 +899,7 @@ fn default_emitter(
source_map.clone(),
pretty,
json_rendered,
external_macro_backtrace,
macro_backtrace,
)
.ui_testing(sopts.debugging_opts.ui_testing()),
),
@ -910,7 +910,7 @@ fn default_emitter(
source_map.clone(),
pretty,
json_rendered,
external_macro_backtrace,
macro_backtrace,
)
.ui_testing(sopts.debugging_opts.ui_testing()),
),

View File

@ -945,14 +945,6 @@ impl SourceMap {
_ => None,
})
}
pub fn call_span_if_macro(&self, sp: Span) -> Span {
if self.span_to_filename(sp.clone()).is_macros() {
if let Some(use_site) = sp.macro_backtrace().last() {
return use_site.call_site;
}
}
sp
}
}
#[derive(Clone)]

View File

@ -227,8 +227,8 @@ fn dtorck_constraint_for_ty<'tcx>(
// In particular, skipping over `_interior` is safe
// because any side-effects from dropping `_interior` can
// only take place through references with lifetimes
// derived from lifetimes attached to the upvars, and we
// *do* incorporate the upvars here.
// derived from lifetimes attached to the upvars and resume
// argument, and we *do* incorporate those here.
constraints.outlives.extend(
substs
@ -236,6 +236,7 @@ fn dtorck_constraint_for_ty<'tcx>(
.upvar_tys(def_id, tcx)
.map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
);
constraints.outlives.push(substs.as_generator().resume_ty(def_id, tcx).into());
}
ty::Adt(def, substs) => {

View File

@ -92,8 +92,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.into(),
GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
});
if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
let generator_substs = substs.as_generator();
self.demand_eqtype(
expr.span,
resume_ty,
generator_substs.resume_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(
expr.span,
yield_ty,
@ -259,8 +265,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => return None,
}
} else {
// Generators cannot have explicit arguments.
vec![]
// Generators with a `()` resume type may be defined with 0 or 1 explicit arguments,
// else they must have exactly 1 argument. For now though, just give up in this case.
return None;
};
let ret_param_ty = projection.skip_binder().ty;

View File

@ -1796,9 +1796,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
src: &'tcx hir::YieldSource,
) -> Ty<'tcx> {
match self.yield_ty {
Some(ty) => {
self.check_expr_coercable_to_type(&value, ty);
match self.resume_yield_tys {
Some((resume_ty, yield_ty)) => {
self.check_expr_coercable_to_type(&value, yield_ty);
resume_ty
}
// Given that this `yield` expression was generated as a result of lowering a `.await`,
// we know that the yield type must be `()`; however, the context won't contain this
@ -1806,6 +1808,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// value's type against `()` (this check should always hold).
None if src == &hir::YieldSource::Await => {
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
self.tcx.mk_unit()
}
_ => {
struct_span_err!(
@ -1815,9 +1818,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"yield expression outside of generator literal"
)
.emit();
self.tcx.mk_unit()
}
}
self.tcx.mk_unit()
}
}

View File

@ -573,7 +573,7 @@ pub struct FnCtxt<'a, 'tcx> {
/// First span of a return site that we find. Used in error messages.
ret_coercion_span: RefCell<Option<Span>>,
yield_ty: Option<Ty<'tcx>>,
resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
ps: RefCell<UnsafetyState>,
@ -1251,6 +1251,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
/// includes yield), it returns back some information about the yield
/// points.
struct GeneratorTypes<'tcx> {
/// Type of generator argument / values returned by `yield`.
resume_ty: Ty<'tcx>,
/// Type of value that is yielded.
yield_ty: Ty<'tcx>,
@ -1311,7 +1314,11 @@ fn check_fn<'a, 'tcx>(
let yield_ty = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
fcx.yield_ty = Some(yield_ty);
// Resume type defaults to `()` if the generator has no argument.
let resume_ty = fn_sig.inputs().get(0).map(|ty| *ty).unwrap_or_else(|| tcx.mk_unit());
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
}
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id));
@ -1364,8 +1371,11 @@ fn check_fn<'a, 'tcx>(
let interior = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
Some(GeneratorTypes {
yield_ty: fcx.yield_ty.unwrap(),
resume_ty,
yield_ty,
interior,
movability: can_be_generator.unwrap(),
})
@ -2767,7 +2777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err_count_on_creation: inh.tcx.sess.err_count(),
ret_coercion: None,
ret_coercion_span: RefCell::new(None),
yield_ty: None,
resume_yield_tys: None,
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
diverges: Cell::new(Diverges::Maybe),
has_errors: Cell::new(false),

View File

@ -1189,7 +1189,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
// and we don't do that for closures.
if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node {
let dummy_args = if gen.is_some() {
&["<yield_ty>", "<return_ty>", "<witness>"][..]
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>"][..]
} else {
&["<closure_kind>", "<closure_signature>"][..]
};

View File

@ -40,7 +40,10 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
// Safe because we're !Unpin + !Drop mapping to a ?Unpin value
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
let _guard = unsafe { set_task_context(cx) };
match gen.resume() {
match gen.resume(
#[cfg(not(bootstrap))]
(),
) {
GeneratorState::Yielded(()) => Poll::Pending,
GeneratorState::Complete(x) => Poll::Ready(x),
}

View File

@ -78,9 +78,9 @@ fn main() {
_zzz(); // #break
a = c;
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume();
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
Pin::new(&mut b).resume(());
Pin::new(&mut b).resume(());
_zzz(); // #break
}

View File

@ -57,11 +57,11 @@ fn main() {
println!("{} {} {}", a, c, d);
};
_zzz(); // #break
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
_zzz(); // #break
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
_zzz(); // #break
Pin::new(&mut b).resume();
Pin::new(&mut b).resume(());
_zzz(); // #break
}

View File

@ -45,7 +45,7 @@ fn main() {
yield;
};
let mut b = move || {
Pin::new(&mut a).resume();
Pin::new(&mut a).resume(());
yield;
};

View File

@ -13,12 +13,12 @@ fn main() {
// START rustc.main-{{closure}}.generator_drop.0.mir
// bb0: {
// _5 = discriminant((*_1));
// switchInt(move _5) -> [0u32: bb4, 3u32: bb7, otherwise: bb8];
// _7 = discriminant((*_1));
// switchInt(move _7) -> [0u32: bb4, 3u32: bb7, otherwise: bb8];
// }
// bb1: {
// StorageDead(_4);
// StorageDead(_3);
// StorageDead(_2);
// goto -> bb5;
// }
// bb2: {
@ -37,8 +37,8 @@ fn main() {
// goto -> bb3;
// }
// bb7: {
// StorageLive(_2);
// StorageLive(_3);
// StorageLive(_4);
// goto -> bb1;
// }
// bb8: {

View File

@ -31,81 +31,81 @@ fn main() {
// START rustc.main-{{closure}}.StateTransform.before.mir
// ...
// let _2: Foo;
// let _3: Foo;
// ...
// let mut _7: Foo;
// let mut _8: Foo;
// ...
// let mut _9: Bar;
// let mut _10: Bar;
// scope 1 {
// debug a => _2;
// let _3: Bar;
// debug a => _3;
// let _4: Bar;
// scope 2 {
// debug b => _3;
// debug b => _4;
// }
// }
// bb0: {
// StorageLive(_2);
// _2 = Foo(const 5i32,);
// StorageLive(_3);
// _3 = Bar(const 6i32,);
// _3 = Foo(const 5i32,);
// StorageLive(_4);
// _4 = Bar(const 6i32,);
// ...
// _1 = suspend(move _5) -> [resume: bb2, drop: bb4];
// _1 = suspend(move _6) -> [resume: bb2, drop: bb4];
// }
// bb1 (cleanup): {
// resume;
// }
// bb2: {
// ...
// StorageLive(_6);
// StorageLive(_7);
// _7 = move _2;
// _6 = const take::<Foo>(move _7) -> [return: bb7, unwind: bb9];
// StorageLive(_8);
// _8 = move _3;
// _7 = const take::<Foo>(move _8) -> [return: bb7, unwind: bb9];
// }
// bb3 (cleanup): {
// StorageDead(_2);
// StorageDead(_3);
// drop(_1) -> bb1;
// }
// bb4: {
// ...
// StorageDead(_3);
// drop(_2) -> [return: bb5, unwind: bb3];
// StorageDead(_4);
// drop(_3) -> [return: bb5, unwind: bb3];
// }
// bb5: {
// StorageDead(_2);
// StorageDead(_3);
// drop(_1) -> [return: bb6, unwind: bb1];
// }
// bb6: {
// generator_drop;
// }
// bb7: {
// StorageDead(_8);
// StorageDead(_7);
// StorageDead(_6);
// StorageLive(_8);
// StorageLive(_9);
// _9 = move _3;
// _8 = const take::<Bar>(move _9) -> [return: bb10, unwind: bb11];
// StorageLive(_10);
// _10 = move _4;
// _9 = const take::<Bar>(move _10) -> [return: bb10, unwind: bb11];
// }
// bb8 (cleanup): {
// StorageDead(_4);
// StorageDead(_3);
// StorageDead(_2);
// drop(_1) -> bb1;
// }
// bb9 (cleanup): {
// StorageDead(_8);
// StorageDead(_7);
// StorageDead(_6);
// goto -> bb8;
// }
// bb10: {
// StorageDead(_10);
// StorageDead(_9);
// StorageDead(_8);
// ...
// StorageDead(_4);
// StorageDead(_3);
// StorageDead(_2);
// drop(_1) -> [return: bb12, unwind: bb1];
// }
// bb11 (cleanup): {
// StorageDead(_10);
// StorageDead(_9);
// StorageDead(_8);
// goto -> bb8;
// }
// bb12: {

View File

@ -16,7 +16,7 @@ fn main() {
yield;
};
panic::catch_unwind(panic::AssertUnwindSafe(|| {
let x = Pin::new(&mut g).resume();
let x = Pin::new(&mut g).resume(());
}));
Pin::new(&mut g).resume();
Pin::new(&mut g).resume(());
}

View File

@ -175,4 +175,5 @@ LL | f!("Foo\nbar [BarF] bar\nbaz");
bar [BarF] bar
^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -42,6 +42,7 @@ LL | #[derive(HashStable)]
|
= note: for more information, see https://github.com/rust-lang/rust/issues/27812
= help: add `#![feature(rustc_private)]` to the crate attributes to enable
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 5 previous errors

View File

@ -21,6 +21,7 @@ LL | custom_lint_pass_macro!();
| -------------------------- in this macro invocation
|
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -5,6 +5,7 @@ LL | static A: usize = 0;
| ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
|
= note: required by `std::alloc::GlobalAlloc::alloc`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
--> $DIR/not-an-allocator.rs:2:1
@ -13,6 +14,7 @@ LL | static A: usize = 0;
| ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
|
= note: required by `std::alloc::GlobalAlloc::dealloc`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
--> $DIR/not-an-allocator.rs:2:1
@ -21,6 +23,7 @@ LL | static A: usize = 0;
| ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
|
= note: required by `std::alloc::GlobalAlloc::realloc`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `usize: std::alloc::GlobalAlloc` is not satisfied
--> $DIR/not-an-allocator.rs:2:1
@ -29,6 +32,7 @@ LL | static A: usize = 0;
| ^^^^^^^^^^^^^^^^^^^^ the trait `std::alloc::GlobalAlloc` is not implemented for `usize`
|
= note: required by `std::alloc::GlobalAlloc::alloc_zeroed`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View File

@ -6,6 +6,8 @@ LL | static A: System = System;
LL | #[global_allocator]
LL | static B: System = System;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
|
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -19,7 +19,7 @@ fn main() {
let mut g = || {
yield;
};
Pin::new(&mut g).resume(); // Yields once.
Pin::new(&mut g).resume(); // Completes here.
Pin::new(&mut g).resume(); // Panics here.
Pin::new(&mut g).resume(()); // Yields once.
Pin::new(&mut g).resume(()); // Completes here.
Pin::new(&mut g).resume(()); // Panics here.
}

View File

@ -9,7 +9,7 @@ LL | x.x[0];
| ------ borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | static settings_dir: String = format!("");
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -9,6 +9,8 @@ LL | aaa!(D);
...
LL | sss!();
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -4,7 +4,7 @@ error: requires at least a format string argument
LL | format!();
| ^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected token: `,`
--> $DIR/bad-format-args.rs:3:16

View File

@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
|
LL | assert!("foo");
| ^^^^^^^^^^^^^^^ cannot apply unary operator `!`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -60,6 +60,8 @@ LL | #[cfg(feature = $expr)]
...
LL | generate_s10!(concat!("nonexistent"));
| -------------------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 10 previous errors

View File

@ -6,6 +6,8 @@ LL | #[cfg_attr(all(), unknown)]
...
LL | foo!();
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -6,6 +6,7 @@ LL | println!("{:?}", [0_usize; 33]);
|
= note: required because of the requirements on the impl of `std::fmt::Debug` for `[usize; 33]`
= note: required by `std::fmt::Debug::fmt`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/core-traits-no-impls-length-33.rs:10:16

View File

@ -15,6 +15,7 @@ LL | struct S<T: Debug, const N: usize>([T; N]);
= note: required because of the requirements on the impl of `std::fmt::Debug` for `[T; _]`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; _]`
= note: required for the cast to the object type `dyn std::fmt::Debug`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -15,6 +15,7 @@ LL | a: [u32; N],
= note: required because of the requirements on the impl of `std::fmt::Debug` for `[u32; _]`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&[u32; _]`
= note: required for the cast to the object type `dyn std::fmt::Debug`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -12,7 +12,7 @@ LL | assert_eq!(Y, 4);
| |
| referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant expression failed
--> $DIR/const_fn_ptr_fail2.rs:22:5
@ -22,7 +22,7 @@ LL | assert_eq!(Z, 4);
| |
| referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -7,7 +7,7 @@ LL | pub const Z: () = panic!("cheese");
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:4:19
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic.rs:7:19
@ -17,7 +17,7 @@ LL | pub const Y: () = unreachable!();
| |
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:7:19
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic.rs:10:19
@ -27,7 +27,7 @@ LL | pub const X: () = unimplemented!();
| |
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:10:19
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -7,7 +7,7 @@ LL | const Z: () = panic!("cheese");
| the evaluated program panicked at 'cheese', $DIR/const_panic_libcore.rs:5:15
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic_libcore.rs:8:15
@ -17,7 +17,7 @@ LL | const Y: () = unreachable!();
| |
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore.rs:8:15
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic_libcore.rs:11:15
@ -27,7 +27,7 @@ LL | const X: () = unimplemented!();
| |
| the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore.rs:11:15
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -7,7 +7,7 @@ LL | const Z: () = panic!("cheese");
| the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:9:15
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic_libcore_main.rs:12:15
@ -17,7 +17,7 @@ LL | const Y: () = unreachable!();
| |
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:12:15
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/const_panic_libcore_main.rs:15:15
@ -27,7 +27,7 @@ LL | const X: () = unimplemented!();
| |
| the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_main.rs:15:15
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -6,7 +6,7 @@ LL | const Z: () = panic!("cheese");
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add `#![feature(const_panic)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: panicking in constants is unstable
--> $DIR/feature-gate-const_panic.rs:9:15
@ -16,7 +16,7 @@ LL | const X: () = unimplemented!();
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add `#![feature(const_panic)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: panicking in constants is unstable
--> $DIR/feature-gate-const_panic.rs:6:15
@ -26,7 +26,7 @@ LL | const Y: () = unreachable!();
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add `#![feature(const_panic)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -11,7 +11,7 @@ note: the lint level is defined here
|
LL | #![warn(const_err)]
| ^^^^^^^^^
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/panic-assoc-never-type.rs:16:13

View File

@ -11,7 +11,7 @@ note: the lint level is defined here
|
LL | #![warn(const_err)]
| ^^^^^^^^^
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/panic-never-type.rs:12:13

View File

@ -5,7 +5,7 @@ LL | static_assert!(2 + 2 == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -7,7 +7,7 @@ LL | const _: () = assert!(false);
| the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:12:15
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | const _: () = assert!(true);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add `#![feature(const_panic)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: panicking in constants is unstable
--> $DIR/assert.rs:12:15
@ -16,7 +16,7 @@ LL | const _: () = assert!(false);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add `#![feature(const_panic)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -6,6 +6,7 @@ LL | const _: () = assert!(true);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `if` is not allowed in a `const`
--> $DIR/assert.rs:12:15
@ -15,6 +16,7 @@ LL | const _: () = assert!(false);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -6,6 +6,7 @@ LL | const _: () = assert!(true);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `if` is not allowed in a `const`
--> $DIR/assert.rs:12:15
@ -15,6 +16,7 @@ LL | const _: () = assert!(false);
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -9,7 +9,7 @@ LL | Drop = assert_eq!(1, 1)
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | Drop = assert_eq!(1, 1)
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `if` is not allowed in a `const`
--> $DIR/issue-50577.rs:7:16
@ -16,7 +16,7 @@ LL | Drop = assert_eq!(1, 1)
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: `match` is not allowed in a `const`
--> $DIR/issue-50577.rs:7:16
@ -26,7 +26,7 @@ LL | Drop = assert_eq!(1, 1)
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0317]: `if` may be missing an `else` clause
--> $DIR/issue-50577.rs:7:16
@ -39,7 +39,7 @@ LL | Drop = assert_eq!(1, 1)
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View File

@ -7,7 +7,7 @@ LL | const _: bool = true || panic!();
| the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:10:25
|
= note: `#[deny(const_err)]` on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error
--> $DIR/short-circuit.rs:11:26
@ -17,7 +17,7 @@ LL | const _: bool = false && panic!();
| |
| the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:11:26
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -10,6 +10,7 @@ LL | | B = T,
LL | | }
| |_- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
|
LL | $( $v = $s::V.try_into().unwrap(), )*
@ -27,6 +28,7 @@ LL | | B = T,
LL | | }
| |_- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
|
LL | $( $v = $s::V.try_into().unwrap(), )*

View File

@ -6,7 +6,7 @@ LL | vec![1, 2, 3]
|
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -4,7 +4,7 @@ error: 1 positional argument in format string, but no arguments were given
LL | myprintln!("{}");
| ^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -8,6 +8,8 @@ LL | _
|
LL | underscore!();
| -------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ LL | fn wrong_kind(){}
| ^^^^^^^^^^^^^^^^^ the trait `example_runner::Testable` is not implemented for `test::TestDescAndFn`
|
= note: required for the cast to the object type `dyn example_runner::Testable`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -9,7 +9,7 @@ note: the lint level is defined here
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -9,7 +9,7 @@ note: the lint level is defined here
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -42,6 +42,8 @@ LL | ($x:expr) => { &$x }
...
LL | foo3(borrow!(0));
| ---------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:36:5
@ -49,7 +51,7 @@ error[E0308]: mismatched types
LL | assert_eq!(3i32, &3i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:39:17

View File

@ -5,6 +5,7 @@ LL | x: Error
| ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
|
= note: required by `std::clone::Clone::clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ LL | Error
| ^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
|
= note: required by `std::clone::Clone::clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ LL | x: Error
| ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
|
= note: required by `std::clone::Clone::clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ LL | Error
| ^^^^^ the trait `std::clone::Clone` is not implemented for `Error`
|
= note: required by `std::clone::Clone::clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -8,6 +8,7 @@ LL | x: Error
= note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
= note: required for the cast to the object type `dyn std::fmt::Debug`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -8,6 +8,7 @@ LL | Error
= note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
= note: required for the cast to the object type `dyn std::fmt::Debug`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -8,6 +8,7 @@ LL | x: Error
= note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&Error`
= note: required for the cast to the object type `dyn std::fmt::Debug`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

Some files were not shown because too many files have changed in this diff Show More