Auto merge of #122966 - matthiaskrgr:rollup-20k8nsm, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #121281 (regression test for #103626) - #122168 (Fix validation on substituted callee bodies in MIR inliner) - #122217 (Handle str literals written with `'` lexed as lifetime) - #122379 (transmute: caution against int2ptr transmutation) - #122840 (`rustdoc --test`: Prevent reaching the maximum size of command-line by using files for arguments if there are too many) - #122907 (Uniquify `ReError` on input mode in canonicalizer) - #122942 (Add test in higher ranked subtype) - #122943 (add a couple more ice tests) - #122963 (core/panicking: fix outdated comment) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
548e14b439
64 changed files with 1757 additions and 171 deletions
|
|
@ -85,7 +85,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||
cfg_checker.check_cleanup_control_flow();
|
||||
|
||||
// Also run the TypeChecker.
|
||||
for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body) {
|
||||
for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) {
|
||||
cfg_checker.fail(location, msg);
|
||||
}
|
||||
|
||||
|
|
@ -541,19 +541,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
|
||||
/// A faster version of the validation pass that only checks those things which may break when
|
||||
/// instantiating any generic parameters.
|
||||
///
|
||||
/// `caller_body` is used to detect cycles in MIR inlining and MIR validation before
|
||||
/// `optimized_mir` is available.
|
||||
pub fn validate_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mir_phase: MirPhase,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
caller_body: &Body<'tcx>,
|
||||
) -> Vec<(Location, String)> {
|
||||
let mut type_checker = TypeChecker { body, tcx, param_env, mir_phase, failures: Vec::new() };
|
||||
let mut type_checker =
|
||||
TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() };
|
||||
type_checker.visit_body(body);
|
||||
type_checker.failures
|
||||
}
|
||||
|
||||
struct TypeChecker<'a, 'tcx> {
|
||||
body: &'a Body<'tcx>,
|
||||
caller_body: &'a Body<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
mir_phase: MirPhase,
|
||||
|
|
@ -705,8 +711,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
&ty::Coroutine(def_id, args) => {
|
||||
let f_ty = if let Some(var) = parent_ty.variant_index {
|
||||
let gen_body = if def_id == self.body.source.def_id() {
|
||||
self.body
|
||||
// If we're currently validating an inlined copy of this body,
|
||||
// then it will no longer be parameterized over the original
|
||||
// args of the coroutine. Otherwise, we prefer to use this body
|
||||
// since we may be in the process of computing this MIR in the
|
||||
// first place.
|
||||
let gen_body = if def_id == self.caller_body.source.def_id() {
|
||||
self.caller_body
|
||||
} else {
|
||||
self.tcx.optimized_mir(def_id)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
|
|||
|
||||
infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
|
||||
infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
|
||||
infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
|
||||
infer_meant_str_literal = if you meant to write a string literal, use double quotes
|
||||
infer_mismatched_static_lifetime = incompatible lifetime on type
|
||||
infer_more_targeted = {$has_param_name ->
|
||||
[true] `{$param_name}`
|
||||
|
|
|
|||
|
|
@ -1339,15 +1339,12 @@ pub enum TypeErrorAdditionalDiags {
|
|||
span: Span,
|
||||
code: String,
|
||||
},
|
||||
#[suggestion(
|
||||
infer_meant_str_literal,
|
||||
code = "\"{code}\"",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
#[multipart_suggestion(infer_meant_str_literal, applicability = "machine-applicable")]
|
||||
MeantStrLiteral {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
code: String,
|
||||
#[suggestion_part(code = "\"")]
|
||||
start: Span,
|
||||
#[suggestion_part(code = "\"")]
|
||||
end: Span,
|
||||
},
|
||||
#[suggestion(
|
||||
infer_consider_specifying_length,
|
||||
|
|
|
|||
|
|
@ -2079,16 +2079,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// If a string was expected and the found expression is a character literal,
|
||||
// perhaps the user meant to write `"s"` to specify a string literal.
|
||||
(ty::Ref(_, r, _), ty::Char) if r.is_str() => {
|
||||
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
|
||||
if let Some(code) =
|
||||
code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
|
||||
{
|
||||
suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
|
||||
span,
|
||||
code: escape_literal(code),
|
||||
})
|
||||
}
|
||||
}
|
||||
suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
|
||||
start: span.with_hi(span.lo() + BytePos(1)),
|
||||
end: span.with_lo(span.hi() - BytePos(1)),
|
||||
})
|
||||
}
|
||||
// For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
|
||||
// we try to suggest to add the missing `let` for `if let Some(..) = expr`
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl<'a> Cursor<'a> {
|
|||
/// If requested position doesn't exist, `EOF_CHAR` is returned.
|
||||
/// However, getting `EOF_CHAR` doesn't always mean actual end of file,
|
||||
/// it should be checked with `is_eof` method.
|
||||
pub(crate) fn first(&self) -> char {
|
||||
pub fn first(&self) -> char {
|
||||
// `.next()` optimizes better than `.nth(0)`
|
||||
self.chars.clone().next().unwrap_or(EOF_CHAR)
|
||||
}
|
||||
|
|
@ -59,6 +59,15 @@ impl<'a> Cursor<'a> {
|
|||
iter.next().unwrap_or(EOF_CHAR)
|
||||
}
|
||||
|
||||
/// Peeks the third symbol from the input stream without consuming it.
|
||||
pub fn third(&self) -> char {
|
||||
// `.next()` optimizes better than `.nth(1)`
|
||||
let mut iter = self.chars.clone();
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.next().unwrap_or(EOF_CHAR)
|
||||
}
|
||||
|
||||
/// Checks if there is nothing more to consume.
|
||||
pub(crate) fn is_eof(&self) -> bool {
|
||||
self.chars.as_str().is_empty()
|
||||
|
|
|
|||
|
|
@ -64,12 +64,9 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
|||
let mut by_move_body = body.clone();
|
||||
MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body);
|
||||
dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
|
||||
by_move_body.source = mir::MirSource {
|
||||
instance: InstanceDef::CoroutineKindShim {
|
||||
coroutine_def_id: coroutine_def_id.to_def_id(),
|
||||
},
|
||||
promoted: None,
|
||||
};
|
||||
by_move_body.source = mir::MirSource::from_instance(InstanceDef::CoroutineKindShim {
|
||||
coroutine_def_id: coroutine_def_id.to_def_id(),
|
||||
});
|
||||
body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
MirPhase::Runtime(RuntimePhase::Optimized),
|
||||
self.param_env,
|
||||
&callee_body,
|
||||
&caller_body,
|
||||
)
|
||||
.is_empty()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
// FIXME: We should investigate the perf implications of not uniquifying
|
||||
// `ReErased`. We may be able to short-circuit registering region
|
||||
// obligations if we encounter a `ReErased` on one side, for example.
|
||||
ty::ReStatic | ty::ReErased => match self.canonicalize_mode {
|
||||
ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
||||
CanonicalizeMode::Response { .. } => return r,
|
||||
},
|
||||
|
|
@ -277,7 +277,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
}
|
||||
}
|
||||
}
|
||||
ty::ReError(_) => return r,
|
||||
};
|
||||
|
||||
let existing_bound_var = match self.canonicalize_mode {
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ parse_more_than_one_char = character literal may only contain one codepoint
|
|||
.remove_non = consider removing the non-printing characters
|
||||
.use_double_quotes = if you meant to write a {$is_byte ->
|
||||
[true] byte string
|
||||
*[false] `str`
|
||||
*[false] string
|
||||
} literal, use double quotes
|
||||
|
||||
parse_multiple_skipped_lines = multiple lines skipped by escaped newline
|
||||
|
|
@ -833,6 +833,7 @@ parse_unknown_prefix = prefix `{$prefix}` is unknown
|
|||
.label = unknown prefix
|
||||
.note = prefixed identifiers and literals are reserved since Rust 2021
|
||||
.suggestion_br = use `br` for a raw byte string
|
||||
.suggestion_str = if you meant to write a string literal, use double quotes
|
||||
.suggestion_whitespace = consider inserting whitespace here
|
||||
|
||||
parse_unknown_start_of_token = unknown start of token: {$escaped}
|
||||
|
|
|
|||
|
|
@ -1987,6 +1987,17 @@ pub enum UnknownPrefixSugg {
|
|||
style = "verbose"
|
||||
)]
|
||||
Whitespace(#[primary_span] Span),
|
||||
#[multipart_suggestion(
|
||||
parse_suggestion_str,
|
||||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
MeantStr {
|
||||
#[suggestion_part(code = "\"")]
|
||||
start: Span,
|
||||
#[suggestion_part(code = "\"")]
|
||||
end: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -2198,12 +2209,21 @@ pub enum MoreThanOneCharSugg {
|
|||
ch: String,
|
||||
},
|
||||
#[suggestion(parse_use_double_quotes, code = "{sugg}", applicability = "machine-applicable")]
|
||||
Quotes {
|
||||
QuotesFull {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
is_byte: bool,
|
||||
sugg: String,
|
||||
},
|
||||
#[multipart_suggestion(parse_use_double_quotes, applicability = "machine-applicable")]
|
||||
Quotes {
|
||||
#[suggestion_part(code = "{prefix}\"")]
|
||||
start: Span,
|
||||
#[suggestion_part(code = "\"")]
|
||||
end: Span,
|
||||
is_byte: bool,
|
||||
prefix: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ pub(crate) fn parse_token_trees<'psess, 'src>(
|
|||
cursor,
|
||||
override_span,
|
||||
nbsp_is_whitespace: false,
|
||||
last_lifetime: None,
|
||||
};
|
||||
let (stream, res, unmatched_delims) =
|
||||
tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
|
||||
|
|
@ -105,6 +106,10 @@ struct StringReader<'psess, 'src> {
|
|||
/// in this file, it's safe to treat further occurrences of the non-breaking
|
||||
/// space character as whitespace.
|
||||
nbsp_is_whitespace: bool,
|
||||
|
||||
/// Track the `Span` for the leading `'` of the last lifetime. Used for
|
||||
/// diagnostics to detect possible typo where `"` was meant.
|
||||
last_lifetime: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'psess, 'src> StringReader<'psess, 'src> {
|
||||
|
|
@ -130,6 +135,18 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
|
|||
|
||||
debug!("next_token: {:?}({:?})", token.kind, self.str_from(start));
|
||||
|
||||
if let rustc_lexer::TokenKind::Semi
|
||||
| rustc_lexer::TokenKind::LineComment { .. }
|
||||
| rustc_lexer::TokenKind::BlockComment { .. }
|
||||
| rustc_lexer::TokenKind::CloseParen
|
||||
| rustc_lexer::TokenKind::CloseBrace
|
||||
| rustc_lexer::TokenKind::CloseBracket = token.kind
|
||||
{
|
||||
// Heuristic: we assume that it is unlikely we're dealing with an unterminated
|
||||
// string surrounded by single quotes.
|
||||
self.last_lifetime = None;
|
||||
}
|
||||
|
||||
// Now "cook" the token, converting the simple `rustc_lexer::TokenKind` enum into a
|
||||
// rich `rustc_ast::TokenKind`. This turns strings into interned symbols and runs
|
||||
// additional validation.
|
||||
|
|
@ -247,6 +264,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
|
|||
// expansion purposes. See #12512 for the gory details of why
|
||||
// this is necessary.
|
||||
let lifetime_name = self.str_from(start);
|
||||
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
|
||||
if starts_with_number {
|
||||
let span = self.mk_sp(start, self.pos);
|
||||
self.dcx().struct_err("lifetimes cannot start with a number")
|
||||
|
|
@ -395,10 +413,21 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
|
|||
match kind {
|
||||
rustc_lexer::LiteralKind::Char { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx()
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
|
||||
.with_code(E0762)
|
||||
.emit()
|
||||
.with_code(E0762);
|
||||
if let Some(lt_sp) = self.last_lifetime {
|
||||
err.multipart_suggestion(
|
||||
"if you meant to write a string literal, use double quotes",
|
||||
vec![
|
||||
(lt_sp, "\"".to_string()),
|
||||
(self.mk_sp(start, start + BytePos(1)), "\"".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err.emit()
|
||||
}
|
||||
self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' '
|
||||
}
|
||||
|
|
@ -669,15 +698,33 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
|
|||
let expn_data = prefix_span.ctxt().outer_expn_data();
|
||||
|
||||
if expn_data.edition >= Edition::Edition2021 {
|
||||
let mut silence = false;
|
||||
// In Rust 2021, this is a hard error.
|
||||
let sugg = if prefix == "rb" {
|
||||
Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
|
||||
} else if expn_data.is_root() {
|
||||
Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
|
||||
if self.cursor.first() == '\''
|
||||
&& let Some(start) = self.last_lifetime
|
||||
&& self.cursor.third() != '\''
|
||||
{
|
||||
// An "unclosed `char`" error will be emitted already, silence redundant error.
|
||||
silence = true;
|
||||
Some(errors::UnknownPrefixSugg::MeantStr {
|
||||
start,
|
||||
end: self.mk_sp(self.pos, self.pos + BytePos(1)),
|
||||
})
|
||||
} else {
|
||||
Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
|
||||
let err = errors::UnknownPrefix { span: prefix_span, prefix, sugg };
|
||||
if silence {
|
||||
self.dcx().create_err(err).delay_as_bug();
|
||||
} else {
|
||||
self.dcx().emit_err(err);
|
||||
}
|
||||
} else {
|
||||
// Before Rust 2021, only emit a lint for migration.
|
||||
self.psess.buffer_lint_with_diagnostic(
|
||||
|
|
|
|||
|
|
@ -95,11 +95,21 @@ pub(crate) fn emit_unescape_error(
|
|||
}
|
||||
escaped.push(c);
|
||||
}
|
||||
let sugg = format!("{prefix}\"{escaped}\"");
|
||||
MoreThanOneCharSugg::Quotes {
|
||||
span: full_lit_span,
|
||||
is_byte: mode == Mode::Byte,
|
||||
sugg,
|
||||
if escaped.len() != lit.len() || full_lit_span.is_empty() {
|
||||
let sugg = format!("{prefix}\"{escaped}\"");
|
||||
MoreThanOneCharSugg::QuotesFull {
|
||||
span: full_lit_span,
|
||||
is_byte: mode == Mode::Byte,
|
||||
sugg,
|
||||
}
|
||||
} else {
|
||||
MoreThanOneCharSugg::Quotes {
|
||||
start: full_lit_span
|
||||
.with_hi(full_lit_span.lo() + BytePos((prefix.len() + 1) as u32)),
|
||||
end: full_lit_span.with_lo(full_lit_span.hi() - BytePos(1)),
|
||||
is_byte: mode == Mode::Byte,
|
||||
prefix,
|
||||
}
|
||||
}
|
||||
});
|
||||
dcx.emit_err(UnescapeError::MoreThanOneChar {
|
||||
|
|
|
|||
|
|
@ -1165,14 +1165,6 @@ extern "rust-intrinsic" {
|
|||
/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
|
||||
/// unsafe**. `transmute` should be the absolute last resort.
|
||||
///
|
||||
/// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub],
|
||||
/// unless the pointer was originally created *from* an integer.
|
||||
/// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling],
|
||||
/// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.)
|
||||
/// Any attempt to use the resulting value for integer operations will abort const-evaluation.
|
||||
/// (And even outside `const`, such transmutation is touching on many unspecified aspects of the
|
||||
/// Rust memory model and should be avoided. See below for alternatives.)
|
||||
///
|
||||
/// Because `transmute` is a by-value operation, alignment of the *transmuted values
|
||||
/// themselves* is not a concern. As with any other function, the compiler already ensures
|
||||
/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
|
||||
|
|
@ -1183,6 +1175,39 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
///
|
||||
/// # Transmutation between pointers and integers
|
||||
///
|
||||
/// Special care has to be taken when transmuting between pointers and integers, e.g.
|
||||
/// transmuting between `*const ()` and `usize`.
|
||||
///
|
||||
/// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless
|
||||
/// the pointer was originally created *from* an integer. (That includes this function
|
||||
/// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling],
|
||||
/// but also semantically-equivalent conversions such as punning through `repr(C)` union
|
||||
/// fields.) Any attempt to use the resulting value for integer operations will abort
|
||||
/// const-evaluation. (And even outside `const`, such transmutation is touching on many
|
||||
/// unspecified aspects of the Rust memory model and should be avoided. See below for
|
||||
/// alternatives.)
|
||||
///
|
||||
/// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not*
|
||||
/// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed
|
||||
/// this way is currently considered undefined behavior.
|
||||
///
|
||||
/// All this also applies when the integer is nested inside an array, tuple, struct, or enum.
|
||||
/// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this
|
||||
/// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling
|
||||
/// `assume_init()` on that result is considered as completing the pointer-to-integer transmute
|
||||
/// and thus runs into the issues discussed above.
|
||||
///
|
||||
/// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a
|
||||
/// lossless process. If you want to round-trip a pointer through an integer in a way that you
|
||||
/// can get back the original pointer, you need to use `as` casts, or replace the integer type
|
||||
/// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to
|
||||
/// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized
|
||||
/// memory due to padding). If you specifically need to store something that is "either an
|
||||
/// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without
|
||||
/// any loss (via `as` casts or via `transmute`).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// There are a few things that `transmute` is really useful for.
|
||||
|
|
|
|||
|
|
@ -132,11 +132,11 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
|
|||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
||||
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
|
||||
pub const fn panic(expr: &'static str) -> ! {
|
||||
// Use Arguments::new_v1 instead of format_args!("{expr}") to potentially
|
||||
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
|
||||
// reduce size overhead. The format_args! macro uses str's Display trait to
|
||||
// write expr, which calls Formatter::pad, which must accommodate string
|
||||
// truncation and padding (even though none is used here). Using
|
||||
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
|
||||
// Arguments::new_const may allow the compiler to omit Formatter::pad from the
|
||||
// output binary, saving up to a few kilobytes.
|
||||
panic_fmt(fmt::Arguments::new_const(&[expr]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ use rustc_span::source_map::SourceMap;
|
|||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Write};
|
||||
use std::panic;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -31,6 +31,8 @@ use std::str;
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use tempfile::{Builder as TempFileBuilder, TempDir};
|
||||
|
||||
use crate::clean::{types::AttributesExt, Attributes};
|
||||
use crate::config::Options as RustdocOptions;
|
||||
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
|
||||
|
|
@ -48,7 +50,55 @@ pub(crate) struct GlobalTestOptions {
|
|||
pub(crate) attrs: Vec<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
|
||||
pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
|
||||
let mut file = File::create(file_path)
|
||||
.map_err(|error| format!("failed to create args file: {error:?}"))?;
|
||||
|
||||
// We now put the common arguments into the file we created.
|
||||
let mut content = vec!["--crate-type=bin".to_string()];
|
||||
|
||||
for cfg in &options.cfgs {
|
||||
content.push(format!("--cfg={cfg}"));
|
||||
}
|
||||
if !options.check_cfgs.is_empty() {
|
||||
content.push("-Zunstable-options".to_string());
|
||||
for check_cfg in &options.check_cfgs {
|
||||
content.push(format!("--check-cfg={check_cfg}"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(sysroot) = &options.maybe_sysroot {
|
||||
content.push(format!("--sysroot={}", sysroot.display()));
|
||||
}
|
||||
for lib_str in &options.lib_strs {
|
||||
content.push(format!("-L{lib_str}"));
|
||||
}
|
||||
for extern_str in &options.extern_strs {
|
||||
content.push(format!("--extern={extern_str}"));
|
||||
}
|
||||
content.push("-Ccodegen-units=1".to_string());
|
||||
for codegen_options_str in &options.codegen_options_strs {
|
||||
content.push(format!("-C{codegen_options_str}"));
|
||||
}
|
||||
for unstable_option_str in &options.unstable_opts_strs {
|
||||
content.push(format!("-Z{unstable_option_str}"));
|
||||
}
|
||||
|
||||
let content = content.join("\n");
|
||||
|
||||
file.write(content.as_bytes())
|
||||
.map_err(|error| format!("failed to write arguments to temporary file: {error:?}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_doctest_dir() -> io::Result<TempDir> {
|
||||
TempFileBuilder::new().prefix("rustdoctest").tempdir()
|
||||
}
|
||||
|
||||
pub(crate) fn run(
|
||||
dcx: &rustc_errors::DiagCtxt,
|
||||
options: RustdocOptions,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let input = config::Input::File(options.input.clone());
|
||||
|
||||
let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
|
||||
|
|
@ -118,6 +168,15 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
|
|||
let externs = options.externs.clone();
|
||||
let json_unused_externs = options.json_unused_externs;
|
||||
|
||||
let temp_dir = match get_doctest_dir()
|
||||
.map_err(|error| format!("failed to create temporary directory: {error:?}"))
|
||||
{
|
||||
Ok(temp_dir) => temp_dir,
|
||||
Err(error) => return crate::wrap_return(dcx, Err(error)),
|
||||
};
|
||||
let file_path = temp_dir.path().join("rustdoc-cfgs");
|
||||
crate::wrap_return(dcx, generate_args_file(&file_path, &options))?;
|
||||
|
||||
let (tests, unused_extern_reports, compiling_test_count) =
|
||||
interface::run_compiler(config, |compiler| {
|
||||
compiler.enter(|queries| {
|
||||
|
|
@ -134,6 +193,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
|
|||
Some(compiler.sess.psess.clone_source_map()),
|
||||
None,
|
||||
enable_per_target_ignores,
|
||||
file_path,
|
||||
);
|
||||
|
||||
let mut hir_collector = HirCollector {
|
||||
|
|
@ -322,44 +382,35 @@ fn run_test(
|
|||
test: &str,
|
||||
crate_name: &str,
|
||||
line: usize,
|
||||
rustdoc_options: RustdocOptions,
|
||||
rustdoc_options: IndividualTestOptions,
|
||||
mut lang_string: LangString,
|
||||
no_run: bool,
|
||||
runtool: Option<String>,
|
||||
runtool_args: Vec<String>,
|
||||
target: TargetTriple,
|
||||
opts: &GlobalTestOptions,
|
||||
edition: Edition,
|
||||
outdir: DirState,
|
||||
path: PathBuf,
|
||||
test_id: &str,
|
||||
report_unused_externs: impl Fn(UnusedExterns),
|
||||
) -> Result<(), TestFailure> {
|
||||
let (test, line_offset, supports_color) =
|
||||
make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
|
||||
let (test, line_offset, supports_color) = make_test(
|
||||
test,
|
||||
Some(crate_name),
|
||||
lang_string.test_harness,
|
||||
opts,
|
||||
edition,
|
||||
Some(&rustdoc_options.test_id),
|
||||
);
|
||||
|
||||
// Make sure we emit well-formed executable names for our target.
|
||||
let rust_out = add_exe_suffix("rust_out".to_owned(), &target);
|
||||
let output_file = outdir.path().join(rust_out);
|
||||
let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
|
||||
let output_file = rustdoc_options.outdir.path().join(rust_out);
|
||||
|
||||
let rustc_binary = rustdoc_options
|
||||
.test_builder
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
|
||||
let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
|
||||
compiler.arg("--crate-type").arg("bin");
|
||||
for cfg in &rustdoc_options.cfgs {
|
||||
compiler.arg("--cfg").arg(&cfg);
|
||||
}
|
||||
if !rustdoc_options.check_cfgs.is_empty() {
|
||||
compiler.arg("-Z").arg("unstable-options");
|
||||
for check_cfg in &rustdoc_options.check_cfgs {
|
||||
compiler.arg("--check-cfg").arg(&check_cfg);
|
||||
}
|
||||
}
|
||||
if let Some(sysroot) = rustdoc_options.maybe_sysroot {
|
||||
compiler.arg("--sysroot").arg(sysroot);
|
||||
}
|
||||
|
||||
compiler.arg(&format!("@{}", rustdoc_options.arg_file.display()));
|
||||
|
||||
compiler.arg("--edition").arg(&edition.to_string());
|
||||
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
|
||||
compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
|
||||
|
|
@ -367,29 +418,17 @@ fn run_test(
|
|||
if lang_string.test_harness {
|
||||
compiler.arg("--test");
|
||||
}
|
||||
if rustdoc_options.json_unused_externs.is_enabled() && !lang_string.compile_fail {
|
||||
if rustdoc_options.is_json_unused_externs_enabled && !lang_string.compile_fail {
|
||||
compiler.arg("--error-format=json");
|
||||
compiler.arg("--json").arg("unused-externs");
|
||||
compiler.arg("-Z").arg("unstable-options");
|
||||
compiler.arg("-W").arg("unused_crate_dependencies");
|
||||
compiler.arg("-Z").arg("unstable-options");
|
||||
}
|
||||
for lib_str in &rustdoc_options.lib_strs {
|
||||
compiler.arg("-L").arg(&lib_str);
|
||||
}
|
||||
for extern_str in &rustdoc_options.extern_strs {
|
||||
compiler.arg("--extern").arg(&extern_str);
|
||||
}
|
||||
compiler.arg("-Ccodegen-units=1");
|
||||
for codegen_options_str in &rustdoc_options.codegen_options_strs {
|
||||
compiler.arg("-C").arg(&codegen_options_str);
|
||||
}
|
||||
for unstable_option_str in &rustdoc_options.unstable_opts_strs {
|
||||
compiler.arg("-Z").arg(&unstable_option_str);
|
||||
}
|
||||
if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
|
||||
|
||||
if no_run && !lang_string.compile_fail && rustdoc_options.should_persist_doctests {
|
||||
compiler.arg("--emit=metadata");
|
||||
}
|
||||
compiler.arg("--target").arg(match target {
|
||||
compiler.arg("--target").arg(match rustdoc_options.target {
|
||||
TargetTriple::TargetTriple(s) => s,
|
||||
TargetTriple::TargetJson { path_for_rustdoc, .. } => {
|
||||
path_for_rustdoc.to_str().expect("target path must be valid unicode").to_string()
|
||||
|
|
@ -485,10 +524,10 @@ fn run_test(
|
|||
let mut cmd;
|
||||
|
||||
let output_file = make_maybe_absolute_path(output_file);
|
||||
if let Some(tool) = runtool {
|
||||
if let Some(tool) = rustdoc_options.runtool {
|
||||
let tool = make_maybe_absolute_path(tool.into());
|
||||
cmd = Command::new(tool);
|
||||
cmd.args(runtool_args);
|
||||
cmd.args(rustdoc_options.runtool_args);
|
||||
cmd.arg(output_file);
|
||||
} else {
|
||||
cmd = Command::new(output_file);
|
||||
|
|
@ -897,6 +936,56 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
|
|||
(before, after, crates)
|
||||
}
|
||||
|
||||
pub(crate) struct IndividualTestOptions {
|
||||
test_builder: Option<PathBuf>,
|
||||
test_builder_wrappers: Vec<PathBuf>,
|
||||
is_json_unused_externs_enabled: bool,
|
||||
should_persist_doctests: bool,
|
||||
error_format: ErrorOutputType,
|
||||
test_run_directory: Option<PathBuf>,
|
||||
nocapture: bool,
|
||||
arg_file: PathBuf,
|
||||
outdir: DirState,
|
||||
runtool: Option<String>,
|
||||
runtool_args: Vec<String>,
|
||||
target: TargetTriple,
|
||||
test_id: String,
|
||||
}
|
||||
|
||||
impl IndividualTestOptions {
|
||||
fn new(options: &RustdocOptions, arg_file: &Path, test_id: String) -> Self {
|
||||
let outdir = if let Some(ref path) = options.persist_doctests {
|
||||
let mut path = path.clone();
|
||||
path.push(&test_id);
|
||||
|
||||
if let Err(err) = std::fs::create_dir_all(&path) {
|
||||
eprintln!("Couldn't create directory for doctest executables: {err}");
|
||||
panic::resume_unwind(Box::new(()));
|
||||
}
|
||||
|
||||
DirState::Perm(path)
|
||||
} else {
|
||||
DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir"))
|
||||
};
|
||||
|
||||
Self {
|
||||
test_builder: options.test_builder.clone(),
|
||||
test_builder_wrappers: options.test_builder_wrappers.clone(),
|
||||
is_json_unused_externs_enabled: options.json_unused_externs.is_enabled(),
|
||||
should_persist_doctests: options.persist_doctests.is_none(),
|
||||
error_format: options.error_format,
|
||||
test_run_directory: options.test_run_directory.clone(),
|
||||
nocapture: options.nocapture,
|
||||
arg_file: arg_file.into(),
|
||||
outdir,
|
||||
runtool: options.runtool.clone(),
|
||||
runtool_args: options.runtool_args.clone(),
|
||||
target: options.target.clone(),
|
||||
test_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait Tester {
|
||||
fn add_test(&mut self, test: String, config: LangString, line: usize);
|
||||
fn get_line(&self) -> usize {
|
||||
|
|
@ -941,6 +1030,7 @@ pub(crate) struct Collector {
|
|||
visited_tests: FxHashMap<(String, usize), usize>,
|
||||
unused_extern_reports: Arc<Mutex<Vec<UnusedExterns>>>,
|
||||
compiling_test_count: AtomicUsize,
|
||||
arg_file: PathBuf,
|
||||
}
|
||||
|
||||
impl Collector {
|
||||
|
|
@ -952,6 +1042,7 @@ impl Collector {
|
|||
source_map: Option<Lrc<SourceMap>>,
|
||||
filename: Option<PathBuf>,
|
||||
enable_per_target_ignores: bool,
|
||||
arg_file: PathBuf,
|
||||
) -> Collector {
|
||||
Collector {
|
||||
tests: Vec::new(),
|
||||
|
|
@ -967,6 +1058,7 @@ impl Collector {
|
|||
visited_tests: FxHashMap::default(),
|
||||
unused_extern_reports: Default::default(),
|
||||
compiling_test_count: AtomicUsize::new(0),
|
||||
arg_file,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1009,13 +1101,9 @@ impl Tester for Collector {
|
|||
let crate_name = self.crate_name.clone();
|
||||
let opts = self.opts.clone();
|
||||
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
|
||||
let rustdoc_options = self.rustdoc_options.clone();
|
||||
let runtool = self.rustdoc_options.runtool.clone();
|
||||
let runtool_args = self.rustdoc_options.runtool_args.clone();
|
||||
let target = self.rustdoc_options.target.clone();
|
||||
let target_str = target.to_string();
|
||||
let target_str = self.rustdoc_options.target.to_string();
|
||||
let unused_externs = self.unused_extern_reports.clone();
|
||||
let no_run = config.no_run || rustdoc_options.no_run;
|
||||
let no_run = config.no_run || self.rustdoc_options.no_run;
|
||||
if !config.compile_fail {
|
||||
self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
|
|
@ -1049,23 +1137,9 @@ impl Tester for Collector {
|
|||
self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
|
||||
},
|
||||
);
|
||||
let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() {
|
||||
path.push(&test_id);
|
||||
|
||||
if let Err(err) = std::fs::create_dir_all(&path) {
|
||||
eprintln!("Couldn't create directory for doctest executables: {err}");
|
||||
panic::resume_unwind(Box::new(()));
|
||||
}
|
||||
|
||||
DirState::Perm(path)
|
||||
} else {
|
||||
DirState::Temp(
|
||||
TempFileBuilder::new()
|
||||
.prefix("rustdoctest")
|
||||
.tempdir()
|
||||
.expect("rustdoc needs a tempdir"),
|
||||
)
|
||||
};
|
||||
let rustdoc_test_options =
|
||||
IndividualTestOptions::new(&self.rustdoc_options, &self.arg_file, test_id);
|
||||
|
||||
debug!("creating test {name}: {test}");
|
||||
self.tests.push(test::TestDescAndFn {
|
||||
|
|
@ -1096,17 +1170,12 @@ impl Tester for Collector {
|
|||
&test,
|
||||
&crate_name,
|
||||
line,
|
||||
rustdoc_options,
|
||||
rustdoc_test_options,
|
||||
config,
|
||||
no_run,
|
||||
runtool,
|
||||
runtool_args,
|
||||
target,
|
||||
&opts,
|
||||
edition,
|
||||
outdir,
|
||||
path,
|
||||
&test_id,
|
||||
report_unused_externs,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -664,7 +664,7 @@ fn usage(argv0: &str) {
|
|||
/// A result type used by several functions under `main()`.
|
||||
type MainResult = Result<(), ErrorGuaranteed>;
|
||||
|
||||
fn wrap_return(dcx: &rustc_errors::DiagCtxt, res: Result<(), String>) -> MainResult {
|
||||
pub(crate) fn wrap_return(dcx: &rustc_errors::DiagCtxt, res: Result<(), String>) -> MainResult {
|
||||
match res {
|
||||
Ok(()) => dcx.has_errors().map_or(Ok(()), Err),
|
||||
Err(err) => Err(dcx.err(err)),
|
||||
|
|
@ -731,7 +731,7 @@ fn main_args(
|
|||
|
||||
match (options.should_test, options.markdown_input()) {
|
||||
(true, true) => return wrap_return(&diag, markdown::test(options)),
|
||||
(true, false) => return doctest::run(options),
|
||||
(true, false) => return doctest::run(&diag, options),
|
||||
(false, true) => {
|
||||
let input = options.input.clone();
|
||||
let edition = options.edition;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@ use std::fs::{create_dir_all, read_to_string, File};
|
|||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
use tempfile::tempdir;
|
||||
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use crate::config::{Options, RenderOptions};
|
||||
use crate::doctest::{Collector, GlobalTestOptions};
|
||||
use crate::doctest::{generate_args_file, Collector, GlobalTestOptions};
|
||||
use crate::html::escape::Escape;
|
||||
use crate::html::markdown;
|
||||
use crate::html::markdown::{
|
||||
|
|
@ -146,6 +148,12 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
|
|||
.map_err(|err| format!("{input}: {err}", input = options.input.display()))?;
|
||||
let mut opts = GlobalTestOptions::default();
|
||||
opts.no_crate_inject = true;
|
||||
|
||||
let temp_dir =
|
||||
tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
|
||||
let file_path = temp_dir.path().join("rustdoc-cfgs");
|
||||
generate_args_file(&file_path, &options)?;
|
||||
|
||||
let mut collector = Collector::new(
|
||||
options.input.display().to_string(),
|
||||
options.clone(),
|
||||
|
|
@ -154,6 +162,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
|
|||
None,
|
||||
Some(options.input),
|
||||
options.enable_per_target_ignores,
|
||||
file_path,
|
||||
);
|
||||
collector.set_position(DUMMY_SP);
|
||||
let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ pub fn out_dir() -> PathBuf {
|
|||
env::var_os("TMPDIR").unwrap().into()
|
||||
}
|
||||
|
||||
fn setup_common_build_cmd() -> Command {
|
||||
let rustc = env::var("RUSTC").unwrap();
|
||||
fn setup_common_build_cmd(command: &str) -> Command {
|
||||
let rustc = env::var(command).unwrap();
|
||||
let mut cmd = Command::new(rustc);
|
||||
cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir());
|
||||
cmd
|
||||
|
|
@ -33,6 +33,10 @@ pub fn aux_build() -> AuxBuildInvocationBuilder {
|
|||
AuxBuildInvocationBuilder::new()
|
||||
}
|
||||
|
||||
pub fn rustdoc() -> Rustdoc {
|
||||
Rustdoc::new()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RustcInvocationBuilder {
|
||||
cmd: Command,
|
||||
|
|
@ -40,7 +44,7 @@ pub struct RustcInvocationBuilder {
|
|||
|
||||
impl RustcInvocationBuilder {
|
||||
fn new() -> Self {
|
||||
let cmd = setup_common_build_cmd();
|
||||
let cmd = setup_common_build_cmd("RUSTC");
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +78,7 @@ pub struct AuxBuildInvocationBuilder {
|
|||
|
||||
impl AuxBuildInvocationBuilder {
|
||||
fn new() -> Self {
|
||||
let mut cmd = setup_common_build_cmd();
|
||||
let mut cmd = setup_common_build_cmd("RUSTC");
|
||||
cmd.arg("--crate-type=lib");
|
||||
Self { cmd }
|
||||
}
|
||||
|
|
@ -97,6 +101,35 @@ impl AuxBuildInvocationBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Rustdoc {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl Rustdoc {
|
||||
fn new() -> Self {
|
||||
let cmd = setup_common_build_cmd("RUSTDOC");
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &str) -> &mut Self {
|
||||
self.cmd.arg(arg);
|
||||
self
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
fn run_common(bin_name: &str) -> (Command, Output) {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
|
|
|
|||
28
tests/mir-opt/inline_coroutine_body.rs
Normal file
28
tests/mir-opt/inline_coroutine_body.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// skip-filecheck
|
||||
//@ unit-test: Inline
|
||||
//@ edition: 2021
|
||||
//@ compile-flags: -Zinline-mir-hint-threshold=10000 -Zinline-mir-threshold=10000 --crate-type=lib
|
||||
|
||||
pub async fn run(permit: ActionPermit<'_, ()>, ctx: &mut core::task::Context<'_>) {
|
||||
run2(permit, ctx);
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_coroutine_body.run2-{closure#0}.Inline.diff
|
||||
fn run2<T>(permit: ActionPermit<'_, T>, ctx: &mut core::task::Context) {
|
||||
_ = || {
|
||||
let mut fut = ActionPermit::perform(permit);
|
||||
let fut = unsafe { core::pin::Pin::new_unchecked(&mut fut) };
|
||||
_ = core::future::Future::poll(fut, ctx);
|
||||
};
|
||||
}
|
||||
|
||||
pub struct ActionPermit<'a, T> {
|
||||
_guard: core::cell::Ref<'a, T>,
|
||||
}
|
||||
|
||||
impl<'a, T> ActionPermit<'a, T> {
|
||||
async fn perform(self) {
|
||||
core::future::ready(()).await
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
- // MIR for `run2::{closure#0}` before Inline
|
||||
+ // MIR for `run2::{closure#0}` after Inline
|
||||
|
||||
fn run2::{closure#0}(_1: {closure@$DIR/inline_coroutine_body.rs:13:9: 13:11}) -> () {
|
||||
debug permit => (_1.0: ActionPermit<'_, T>);
|
||||
debug ctx => (*(_1.1: &mut std::task::Context<'_>));
|
||||
let mut _0: ();
|
||||
let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _3: ActionPermit<'_, T>;
|
||||
let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let _6: ();
|
||||
let mut _7: std::task::Poll<()>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let mut _9: &mut std::task::Context<'_>;
|
||||
let mut _10: &mut std::task::Context<'_>;
|
||||
scope 1 {
|
||||
debug fut => _2;
|
||||
let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
scope 2 {
|
||||
debug fut => _4;
|
||||
scope 4 {
|
||||
}
|
||||
+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
|
||||
+ debug _task_context => _31;
|
||||
+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
|
||||
+ let _11: ActionPermit<'_, T>;
|
||||
+ let mut _12: std::future::Ready<()>;
|
||||
+ let mut _13: std::future::Ready<()>;
|
||||
+ let mut _14: ();
|
||||
+ let mut _16: ();
|
||||
+ let _17: ();
|
||||
+ let mut _18: std::task::Poll<()>;
|
||||
+ let mut _19: std::pin::Pin<&mut std::future::Ready<()>>;
|
||||
+ let mut _20: &mut std::future::Ready<()>;
|
||||
+ let mut _21: &mut std::future::Ready<()>;
|
||||
+ let mut _22: &mut std::task::Context<'_>;
|
||||
+ let mut _23: &mut std::task::Context<'_>;
|
||||
+ let mut _24: &mut std::task::Context<'_>;
|
||||
+ let mut _25: isize;
|
||||
+ let mut _27: !;
|
||||
+ let mut _28: &mut std::task::Context<'_>;
|
||||
+ let mut _29: ();
|
||||
+ let mut _30: ();
|
||||
+ let mut _31: &mut std::task::Context<'_>;
|
||||
+ let mut _32: u32;
|
||||
+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ scope 8 {
|
||||
+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ let mut _15: std::future::Ready<()>;
|
||||
+ scope 9 {
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
|
||||
+ let _26: ();
|
||||
+ scope 10 {
|
||||
+ }
|
||||
+ scope 11 {
|
||||
+ debug result => _26;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 12 (inlined ready::<()>) {
|
||||
+ debug t => _14;
|
||||
+ let mut _41: std::option::Option<()>;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
scope 3 {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
|
||||
+ debug pointer => _5;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ scope 5 (inlined ActionPermit::<'_, T>::perform) {
|
||||
+ debug self => _3;
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = move (_1.0: ActionPermit<'_, T>);
|
||||
- _2 = ActionPermit::<'_, T>::perform(move _3) -> [return: bb1, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
+ _2 = {coroutine@$DIR/inline_coroutine_body.rs:25:28: 27:6 (#0)} { self: move _3 };
|
||||
StorageDead(_3);
|
||||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = &mut _2;
|
||||
- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = move _4;
|
||||
StorageLive(_9);
|
||||
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
|
||||
_9 = &mut (*_10);
|
||||
- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
|
||||
+ StorageLive(_11);
|
||||
+ StorageLive(_15);
|
||||
+ StorageLive(_16);
|
||||
+ StorageLive(_25);
|
||||
+ StorageLive(_27);
|
||||
+ StorageLive(_30);
|
||||
+ StorageLive(_31);
|
||||
+ StorageLive(_32);
|
||||
+ StorageLive(_33);
|
||||
+ StorageLive(_34);
|
||||
+ StorageLive(_35);
|
||||
+ StorageLive(_36);
|
||||
+ StorageLive(_37);
|
||||
+ StorageLive(_38);
|
||||
+ StorageLive(_39);
|
||||
+ StorageLive(_40);
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _32 = discriminant((*_33));
|
||||
+ switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8];
|
||||
}
|
||||
|
||||
- bb3: {
|
||||
+ bb1: {
|
||||
+ StorageDead(_2);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bb2: {
|
||||
+ StorageDead(_40);
|
||||
+ StorageDead(_39);
|
||||
+ StorageDead(_38);
|
||||
+ StorageDead(_37);
|
||||
+ StorageDead(_36);
|
||||
+ StorageDead(_35);
|
||||
+ StorageDead(_34);
|
||||
+ StorageDead(_33);
|
||||
+ StorageDead(_32);
|
||||
+ StorageDead(_31);
|
||||
+ StorageDead(_30);
|
||||
+ StorageDead(_27);
|
||||
+ StorageDead(_25);
|
||||
+ StorageDead(_16);
|
||||
+ StorageDead(_15);
|
||||
+ StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
_6 = const ();
|
||||
StorageDead(_6);
|
||||
_0 = const ();
|
||||
StorageDead(_4);
|
||||
- drop(_2) -> [return: bb4, unwind unreachable];
|
||||
+ drop(_2) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
+ bb3: {
|
||||
+ _31 = move _9;
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_13);
|
||||
+ StorageLive(_14);
|
||||
+ _14 = ();
|
||||
+ StorageLive(_41);
|
||||
+ _41 = Option::<()>::Some(_14);
|
||||
+ _13 = std::future::Ready::<()>(move _41);
|
||||
+ StorageDead(_41);
|
||||
+ StorageDead(_14);
|
||||
+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb4, unwind unreachable];
|
||||
+ }
|
||||
+
|
||||
bb4: {
|
||||
- StorageDead(_2);
|
||||
- return;
|
||||
+ StorageDead(_13);
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
|
||||
+ goto -> bb5;
|
||||
+ }
|
||||
+
|
||||
+ bb5: {
|
||||
+ StorageLive(_17);
|
||||
+ StorageLive(_18);
|
||||
+ StorageLive(_19);
|
||||
+ StorageLive(_20);
|
||||
+ StorageLive(_21);
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable];
|
||||
+ }
|
||||
+
|
||||
+ bb6: {
|
||||
+ StorageDead(_20);
|
||||
+ StorageLive(_22);
|
||||
+ StorageLive(_23);
|
||||
+ StorageLive(_24);
|
||||
+ _24 = _31;
|
||||
+ _23 = move _24;
|
||||
+ _22 = &mut (*_23);
|
||||
+ StorageDead(_24);
|
||||
+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb7, unwind unreachable];
|
||||
+ }
|
||||
+
|
||||
+ bb7: {
|
||||
+ StorageDead(_22);
|
||||
+ StorageDead(_19);
|
||||
+ _25 = discriminant(_18);
|
||||
+ switchInt(move _25) -> [0: bb10, 1: bb9, otherwise: bb8];
|
||||
+ }
|
||||
+
|
||||
+ bb8: {
|
||||
+ unreachable;
|
||||
+ }
|
||||
+
|
||||
+ bb9: {
|
||||
+ _17 = const ();
|
||||
+ StorageDead(_23);
|
||||
+ StorageDead(_21);
|
||||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageLive(_28);
|
||||
+ StorageLive(_29);
|
||||
+ _29 = ();
|
||||
+ _7 = Poll::<()>::Pending;
|
||||
+ StorageDead(_12);
|
||||
+ StorageDead(_28);
|
||||
+ StorageDead(_29);
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ discriminant((*_38)) = 3;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
+
|
||||
+ bb10: {
|
||||
+ StorageLive(_26);
|
||||
+ _26 = ((_18 as Ready).0: ());
|
||||
+ _30 = _26;
|
||||
+ StorageDead(_26);
|
||||
+ StorageDead(_23);
|
||||
+ StorageDead(_21);
|
||||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageDead(_12);
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable];
|
||||
+ }
|
||||
+
|
||||
+ bb11: {
|
||||
+ _7 = Poll::<()>::Ready(move _30);
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ discriminant((*_40)) = 1;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
+
|
||||
+ bb12: {
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_28);
|
||||
+ StorageLive(_29);
|
||||
+ _28 = move _9;
|
||||
+ StorageDead(_29);
|
||||
+ _31 = move _28;
|
||||
+ StorageDead(_28);
|
||||
+ _16 = const ();
|
||||
+ goto -> bb5;
|
||||
+ }
|
||||
+
|
||||
+ bb13: {
|
||||
+ assert(const false, "`async fn` resumed after completion") -> [success: bb13, unwind unreachable];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
- // MIR for `run2::{closure#0}` before Inline
|
||||
+ // MIR for `run2::{closure#0}` after Inline
|
||||
|
||||
fn run2::{closure#0}(_1: {closure@$DIR/inline_coroutine_body.rs:13:9: 13:11}) -> () {
|
||||
debug permit => (_1.0: ActionPermit<'_, T>);
|
||||
debug ctx => (*(_1.1: &mut std::task::Context<'_>));
|
||||
let mut _0: ();
|
||||
let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _3: ActionPermit<'_, T>;
|
||||
let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let _6: ();
|
||||
let mut _7: std::task::Poll<()>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let mut _9: &mut std::task::Context<'_>;
|
||||
let mut _10: &mut std::task::Context<'_>;
|
||||
scope 1 {
|
||||
debug fut => _2;
|
||||
let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
scope 2 {
|
||||
debug fut => _4;
|
||||
scope 4 {
|
||||
}
|
||||
+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
|
||||
+ debug _task_context => _31;
|
||||
+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
|
||||
+ let _11: ActionPermit<'_, T>;
|
||||
+ let mut _12: std::future::Ready<()>;
|
||||
+ let mut _13: std::future::Ready<()>;
|
||||
+ let mut _14: ();
|
||||
+ let mut _16: ();
|
||||
+ let _17: ();
|
||||
+ let mut _18: std::task::Poll<()>;
|
||||
+ let mut _19: std::pin::Pin<&mut std::future::Ready<()>>;
|
||||
+ let mut _20: &mut std::future::Ready<()>;
|
||||
+ let mut _21: &mut std::future::Ready<()>;
|
||||
+ let mut _22: &mut std::task::Context<'_>;
|
||||
+ let mut _23: &mut std::task::Context<'_>;
|
||||
+ let mut _24: &mut std::task::Context<'_>;
|
||||
+ let mut _25: isize;
|
||||
+ let mut _27: !;
|
||||
+ let mut _28: &mut std::task::Context<'_>;
|
||||
+ let mut _29: ();
|
||||
+ let mut _30: ();
|
||||
+ let mut _31: &mut std::task::Context<'_>;
|
||||
+ let mut _32: u32;
|
||||
+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _41: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _42: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ scope 8 {
|
||||
+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ let mut _15: std::future::Ready<()>;
|
||||
+ scope 9 {
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
|
||||
+ let _26: ();
|
||||
+ scope 10 {
|
||||
+ }
|
||||
+ scope 11 {
|
||||
+ debug result => _26;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 12 (inlined ready::<()>) {
|
||||
+ debug t => _14;
|
||||
+ let mut _43: std::option::Option<()>;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
scope 3 {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
|
||||
+ debug pointer => _5;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ scope 5 (inlined ActionPermit::<'_, T>::perform) {
|
||||
+ debug self => _3;
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = move (_1.0: ActionPermit<'_, T>);
|
||||
- _2 = ActionPermit::<'_, T>::perform(move _3) -> [return: bb1, unwind: bb6];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
+ _2 = {coroutine@$DIR/inline_coroutine_body.rs:25:28: 27:6 (#0)} { self: move _3 };
|
||||
StorageDead(_3);
|
||||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = &mut _2;
|
||||
- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = move _4;
|
||||
StorageLive(_9);
|
||||
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
|
||||
_9 = &mut (*_10);
|
||||
- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
|
||||
+ StorageLive(_11);
|
||||
+ StorageLive(_15);
|
||||
+ StorageLive(_16);
|
||||
+ StorageLive(_25);
|
||||
+ StorageLive(_27);
|
||||
+ StorageLive(_30);
|
||||
+ StorageLive(_31);
|
||||
+ StorageLive(_32);
|
||||
+ StorageLive(_33);
|
||||
+ StorageLive(_34);
|
||||
+ StorageLive(_35);
|
||||
+ StorageLive(_36);
|
||||
+ StorageLive(_37);
|
||||
+ StorageLive(_38);
|
||||
+ StorageLive(_39);
|
||||
+ StorageLive(_40);
|
||||
+ StorageLive(_41);
|
||||
+ StorageLive(_42);
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _32 = discriminant((*_33));
|
||||
+ switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10];
|
||||
}
|
||||
|
||||
- bb3: {
|
||||
+ bb1: {
|
||||
+ StorageDead(_2);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bb2 (cleanup): {
|
||||
+ drop(_2) -> [return: bb3, unwind terminate(cleanup)];
|
||||
+ }
|
||||
+
|
||||
+ bb3 (cleanup): {
|
||||
+ resume;
|
||||
+ }
|
||||
+
|
||||
+ bb4: {
|
||||
+ StorageDead(_42);
|
||||
+ StorageDead(_41);
|
||||
+ StorageDead(_40);
|
||||
+ StorageDead(_39);
|
||||
+ StorageDead(_38);
|
||||
+ StorageDead(_37);
|
||||
+ StorageDead(_36);
|
||||
+ StorageDead(_35);
|
||||
+ StorageDead(_34);
|
||||
+ StorageDead(_33);
|
||||
+ StorageDead(_32);
|
||||
+ StorageDead(_31);
|
||||
+ StorageDead(_30);
|
||||
+ StorageDead(_27);
|
||||
+ StorageDead(_25);
|
||||
+ StorageDead(_16);
|
||||
+ StorageDead(_15);
|
||||
+ StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
_6 = const ();
|
||||
StorageDead(_6);
|
||||
_0 = const ();
|
||||
StorageDead(_4);
|
||||
- drop(_2) -> [return: bb4, unwind: bb6];
|
||||
+ drop(_2) -> [return: bb1, unwind: bb3];
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
- StorageDead(_2);
|
||||
- return;
|
||||
+ bb5: {
|
||||
+ _31 = move _9;
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_13);
|
||||
+ StorageLive(_14);
|
||||
+ _14 = ();
|
||||
+ StorageLive(_43);
|
||||
+ _43 = Option::<()>::Some(_14);
|
||||
+ _13 = std::future::Ready::<()>(move _43);
|
||||
+ StorageDead(_43);
|
||||
+ StorageDead(_14);
|
||||
+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb6, unwind: bb17];
|
||||
}
|
||||
|
||||
- bb5 (cleanup): {
|
||||
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
|
||||
+ bb6: {
|
||||
+ StorageDead(_13);
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
|
||||
+ goto -> bb7;
|
||||
}
|
||||
|
||||
- bb6 (cleanup): {
|
||||
- resume;
|
||||
+ bb7: {
|
||||
+ StorageLive(_17);
|
||||
+ StorageLive(_18);
|
||||
+ StorageLive(_19);
|
||||
+ StorageLive(_20);
|
||||
+ StorageLive(_21);
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15];
|
||||
+ }
|
||||
+
|
||||
+ bb8: {
|
||||
+ StorageDead(_20);
|
||||
+ StorageLive(_22);
|
||||
+ StorageLive(_23);
|
||||
+ StorageLive(_24);
|
||||
+ _24 = _31;
|
||||
+ _23 = move _24;
|
||||
+ _22 = &mut (*_23);
|
||||
+ StorageDead(_24);
|
||||
+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb9, unwind: bb14];
|
||||
+ }
|
||||
+
|
||||
+ bb9: {
|
||||
+ StorageDead(_22);
|
||||
+ StorageDead(_19);
|
||||
+ _25 = discriminant(_18);
|
||||
+ switchInt(move _25) -> [0: bb12, 1: bb11, otherwise: bb10];
|
||||
+ }
|
||||
+
|
||||
+ bb10: {
|
||||
+ unreachable;
|
||||
+ }
|
||||
+
|
||||
+ bb11: {
|
||||
+ _17 = const ();
|
||||
+ StorageDead(_23);
|
||||
+ StorageDead(_21);
|
||||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageLive(_28);
|
||||
+ StorageLive(_29);
|
||||
+ _29 = ();
|
||||
+ _7 = Poll::<()>::Pending;
|
||||
+ StorageDead(_12);
|
||||
+ StorageDead(_28);
|
||||
+ StorageDead(_29);
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ discriminant((*_38)) = 3;
|
||||
+ goto -> bb4;
|
||||
+ }
|
||||
+
|
||||
+ bb12: {
|
||||
+ StorageLive(_26);
|
||||
+ _26 = ((_18 as Ready).0: ());
|
||||
+ _30 = _26;
|
||||
+ StorageDead(_26);
|
||||
+ StorageDead(_23);
|
||||
+ StorageDead(_21);
|
||||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageDead(_12);
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19];
|
||||
+ }
|
||||
+
|
||||
+ bb13: {
|
||||
+ _7 = Poll::<()>::Ready(move _30);
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ discriminant((*_40)) = 1;
|
||||
+ goto -> bb4;
|
||||
+ }
|
||||
+
|
||||
+ bb14 (cleanup): {
|
||||
+ StorageDead(_22);
|
||||
+ StorageDead(_19);
|
||||
+ StorageDead(_23);
|
||||
+ goto -> bb16;
|
||||
+ }
|
||||
+
|
||||
+ bb15 (cleanup): {
|
||||
+ StorageDead(_20);
|
||||
+ StorageDead(_19);
|
||||
+ goto -> bb16;
|
||||
+ }
|
||||
+
|
||||
+ bb16 (cleanup): {
|
||||
+ StorageDead(_21);
|
||||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ goto -> bb18;
|
||||
+ }
|
||||
+
|
||||
+ bb17 (cleanup): {
|
||||
+ StorageDead(_13);
|
||||
+ goto -> bb18;
|
||||
+ }
|
||||
+
|
||||
+ bb18 (cleanup): {
|
||||
+ StorageDead(_12);
|
||||
+ _41 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)];
|
||||
+ }
|
||||
+
|
||||
+ bb19 (cleanup): {
|
||||
+ _42 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ discriminant((*_42)) = 2;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
+
|
||||
+ bb20: {
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_28);
|
||||
+ StorageLive(_29);
|
||||
+ _28 = move _9;
|
||||
+ StorageDead(_29);
|
||||
+ _31 = move _28;
|
||||
+ StorageDead(_28);
|
||||
+ _16 = const ();
|
||||
+ goto -> bb7;
|
||||
+ }
|
||||
+
|
||||
+ bb21: {
|
||||
+ assert(const false, "`async fn` resumed after panicking") -> [success: bb21, unwind: bb2];
|
||||
+ }
|
||||
+
|
||||
+ bb22: {
|
||||
+ assert(const false, "`async fn` resumed after completion") -> [success: bb22, unwind: bb2];
|
||||
}
|
||||
}
|
||||
|
||||
3
tests/run-make/rustdoc-test-args/foo.rs
Normal file
3
tests/run-make/rustdoc-test-args/foo.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
//! ```
|
||||
//! let x = 12;
|
||||
//! ```
|
||||
18
tests/run-make/rustdoc-test-args/rmake.rs
Normal file
18
tests/run-make/rustdoc-test-args/rmake.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::{out_dir, rustdoc};
|
||||
use std::{fs, iter};
|
||||
use std::path::Path;
|
||||
|
||||
fn generate_a_lot_of_cfgs(path: &Path) {
|
||||
let content = iter::repeat("--cfg=a\n").take(100_000).collect::<String>();
|
||||
fs::write(path, content.as_bytes()).expect("failed to create args file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let arg_file = out_dir().join("args");
|
||||
generate_a_lot_of_cfgs(&arg_file);
|
||||
|
||||
let arg_file = format!("@{}", arg_file.display());
|
||||
rustdoc().arg("--test").arg(&arg_file).arg("foo.rs").run();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// issue: rust-lang/rust#104779
|
||||
// ICE region infer, IndexMap: key not found
|
||||
|
||||
struct Inv<'a>(&'a mut &'a ());
|
||||
enum Foo<T> {
|
||||
Bar,
|
||||
Var(T),
|
||||
}
|
||||
type Subtype = Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>;
|
||||
type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
|
||||
|
||||
fn foo() -> impl Sized {
|
||||
//~^ WARN function cannot return without recursing
|
||||
loop {
|
||||
match foo() {
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
//~^^ ERROR higher-ranked subtype error
|
||||
Subtype::Bar => (),
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
//~^^ ERROR higher-ranked subtype error
|
||||
Supertype::Var(x) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:12:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
...
|
||||
LL | match foo() {
|
||||
| ----- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15
|
||||
|
|
||||
LL | match foo() {
|
||||
| ^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15
|
||||
|
|
||||
LL | match foo() {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13
|
||||
|
|
||||
LL | Subtype::Bar => (),
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13
|
||||
|
|
||||
LL | Subtype::Bar => (),
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// issue: rust-lang/rust#106423
|
||||
// ICE collection encountered polymorphic constant: UnevaluatedConst {..}
|
||||
//@ edition:2021
|
||||
//@ check-pass
|
||||
|
||||
#![feature(generic_const_exprs, generic_arg_infer)]
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(unused)]
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub struct Arr<T, const N: usize> {
|
||||
v: [MaybeUninit<T>; N],
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Arr<T, N> {
|
||||
const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
const INIT: [MaybeUninit<T>; N] = [Self::ELEM; N]; // important for optimization of `new`
|
||||
|
||||
fn new() -> Self {
|
||||
Arr { v: Self::INIT }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BaFormatFilter<const N: usize> {}
|
||||
|
||||
pub enum DigitalFilter<const N: usize>
|
||||
where
|
||||
[(); N * 2 + 1]: Sized,
|
||||
[(); N * 2]: Sized,
|
||||
{
|
||||
Ba(BaFormatFilter<{ N * 2 + 1 }>),
|
||||
}
|
||||
|
||||
pub fn iirfilter_st_copy<const N: usize, const M: usize>(_: [f32; M]) -> DigitalFilter<N>
|
||||
where
|
||||
[(); N * 2 + 1]: Sized,
|
||||
[(); N * 2]: Sized,
|
||||
{
|
||||
let zpk = zpk2tf_st(&Arr::<f32, { N * 2 }>::new(), &Arr::<f32, { N * 2 }>::new());
|
||||
DigitalFilter::Ba(zpk)
|
||||
}
|
||||
|
||||
pub fn zpk2tf_st<const N: usize>(
|
||||
_z: &Arr<f32, N>,
|
||||
_p: &Arr<f32, N>,
|
||||
) -> BaFormatFilter<{ N + 1 }>
|
||||
where
|
||||
[(); N + 1]: Sized,
|
||||
{
|
||||
BaFormatFilter {}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
iirfilter_st_copy::<4, 2>([10., 50.,]);
|
||||
}
|
||||
16
tests/ui/drop/norm-ice-106444.rs
Normal file
16
tests/ui/drop/norm-ice-106444.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// issue: rust-lang/rust#106444
|
||||
// ICE failed to normalize
|
||||
//@ compile-flags: -Zmir-opt-level=3
|
||||
//@ check-pass
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
pub trait A {
|
||||
type B;
|
||||
}
|
||||
|
||||
pub struct S<T: A>(T::B);
|
||||
|
||||
pub fn foo<T: A>(p: *mut S<T>) {
|
||||
unsafe { core::ptr::drop_in_place(p) };
|
||||
}
|
||||
17
tests/ui/higher-ranked/structually-relate-aliases.rs
Normal file
17
tests/ui/higher-ranked/structually-relate-aliases.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// regression test for issue #121649.
|
||||
|
||||
trait ToUnit<'a> {
|
||||
type Unit;
|
||||
}
|
||||
|
||||
trait Overlap<T> {}
|
||||
|
||||
type Assoc<'a, T> = <T as ToUnit<'a>>::Unit;
|
||||
|
||||
impl<T> Overlap<T> for T {}
|
||||
|
||||
impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
|
||||
//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
|
||||
//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
|
||||
|
||||
fn main() {}
|
||||
27
tests/ui/higher-ranked/structually-relate-aliases.stderr
Normal file
27
tests/ui/higher-ranked/structually-relate-aliases.stderr
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
|
||||
error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
|
||||
--> $DIR/structually-relate-aliases.rs:13:36
|
||||
|
|
||||
LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
|
||||
| ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
|
||||
--> $DIR/structually-relate-aliases.rs:13:17
|
||||
|
|
||||
LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
12
tests/ui/impl-trait/recursive-ice-101862.rs
Normal file
12
tests/ui/impl-trait/recursive-ice-101862.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// issue: rust-lang/rust#101852
|
||||
// ICE opaque type with non-universal region substs
|
||||
|
||||
pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
|
||||
//~^ WARN function cannot return without recursing
|
||||
vec![].append(&mut ice(x.as_ref()));
|
||||
//~^ ERROR expected generic type parameter, found `&str`
|
||||
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
24
tests/ui/impl-trait/recursive-ice-101862.stderr
Normal file
24
tests/ui/impl-trait/recursive-ice-101862.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/recursive-ice-101862.rs:4:1
|
||||
|
|
||||
LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | vec![].append(&mut ice(x.as_ref()));
|
||||
| --------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error[E0792]: expected generic type parameter, found `&str`
|
||||
--> $DIR/recursive-ice-101862.rs:6:5
|
||||
|
|
||||
LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
|
||||
| --------------- this generic parameter must be used with a generic type parameter
|
||||
LL |
|
||||
LL | vec![].append(&mut ice(x.as_ref()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
@ -4,7 +4,7 @@ error: character literal may only contain one codepoint
|
|||
LL | let _: &str = '"""';
|
||||
| ^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _: &str = "\"\"\"";
|
||||
| ~~~~~~~~
|
||||
|
|
@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let _: &str = '\"\"\"';
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _: &str = "\"\"\"";
|
||||
| ~~~~~~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/str-as-char.rs:10:19
|
||||
|
|
@ -26,7 +26,7 @@ error: character literal may only contain one codepoint
|
|||
LL | let _: &str = '"\"\"\\"\\"';
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _: &str = "\"\"\\"\\"\\\"";
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -39,10 +39,10 @@ LL | let _: &str = 'a';
|
|||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _: &str = "a";
|
||||
| ~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ error[E0308]: mismatched types
|
|||
LL | let v: Vec(&str) = vec!['1', '2'];
|
||||
| ^^^ expected `&str`, found `char`
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let v: Vec(&str) = vec!["1", '2'];
|
||||
| ~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
|
|||
LL | 'nope'
|
||||
| ^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | "nope"
|
||||
| ~~~~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
|
|||
LL | static c: char = '●●';
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | static c: char = "●●";
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/lex-bad-char-literals-3.rs:5:20
|
||||
|
|
@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let ch: &str = '●●';
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let ch: &str = "●●";
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
|
|||
LL | static c: char = '\x10\x10';
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | static c: char = "\x10\x10";
|
||||
| ~~~~~~~~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/lex-bad-char-literals-5.rs:5:20
|
||||
|
|
@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let ch: &str = '\x10\x10';
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let ch: &str = "\x10\x10";
|
||||
| ~~~~~~~~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let x: &str = 'ab';
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let x: &str = "ab";
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/lex-bad-char-literals-6.rs:4:19
|
||||
|
|
@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let y: char = 'cd';
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let y: char = "cd";
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/lex-bad-char-literals-6.rs:6:13
|
||||
|
|
@ -26,10 +26,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let z = 'ef';
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let z = "ef";
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/lex-bad-char-literals-6.rs:13:20
|
||||
|
|
|
|||
6
tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed
Normal file
6
tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//@ run-rustfix
|
||||
fn main() {
|
||||
println!("1 + 1");
|
||||
//~^ ERROR unterminated character literal
|
||||
//~| ERROR lifetimes cannot start with a number
|
||||
}
|
||||
6
tests/ui/lexer/lex-bad-str-literal-as-char-1.rs
Normal file
6
tests/ui/lexer/lex-bad-str-literal-as-char-1.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//@ run-rustfix
|
||||
fn main() {
|
||||
println!('1 + 1');
|
||||
//~^ ERROR unterminated character literal
|
||||
//~| ERROR lifetimes cannot start with a number
|
||||
}
|
||||
20
tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr
Normal file
20
tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
error[E0762]: unterminated character literal
|
||||
--> $DIR/lex-bad-str-literal-as-char-1.rs:3:20
|
||||
|
|
||||
LL | println!('1 + 1');
|
||||
| ^^^
|
||||
|
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!("1 + 1");
|
||||
| ~ ~
|
||||
|
||||
error: lifetimes cannot start with a number
|
||||
--> $DIR/lex-bad-str-literal-as-char-1.rs:3:14
|
||||
|
|
||||
LL | println!('1 + 1');
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0762`.
|
||||
4
tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed
Normal file
4
tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//@ run-rustfix
|
||||
fn main() {
|
||||
println!(" 1 + 1"); //~ ERROR character literal may only contain one codepoint
|
||||
}
|
||||
4
tests/ui/lexer/lex-bad-str-literal-as-char-2.rs
Normal file
4
tests/ui/lexer/lex-bad-str-literal-as-char-2.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//@ run-rustfix
|
||||
fn main() {
|
||||
println!(' 1 + 1'); //~ ERROR character literal may only contain one codepoint
|
||||
}
|
||||
13
tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr
Normal file
13
tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error: character literal may only contain one codepoint
|
||||
--> $DIR/lex-bad-str-literal-as-char-2.rs:3:14
|
||||
|
|
||||
LL | println!(' 1 + 1');
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!(" 1 + 1");
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
7
tests/ui/lexer/lex-bad-str-literal-as-char-3.rs
Normal file
7
tests/ui/lexer/lex-bad-str-literal-as-char-3.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
//@ revisions: rust2015 rust2018 rust2021
|
||||
//@[rust2018] edition:2018
|
||||
//@[rust2021] edition:2021
|
||||
fn main() {
|
||||
println!('hello world');
|
||||
//[rust2015,rust2018,rust2021]~^ ERROR unterminated character literal
|
||||
}
|
||||
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr
Normal file
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0762]: unterminated character literal
|
||||
--> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
|
||||
|
|
||||
LL | println!('hello world');
|
||||
| ^^^
|
||||
|
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!("hello world");
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0762`.
|
||||
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr
Normal file
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0762]: unterminated character literal
|
||||
--> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
|
||||
|
|
||||
LL | println!('hello world');
|
||||
| ^^^
|
||||
|
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!("hello world");
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0762`.
|
||||
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr
Normal file
14
tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0762]: unterminated character literal
|
||||
--> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
|
||||
|
|
||||
LL | println!('hello world');
|
||||
| ^^^
|
||||
|
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!("hello world");
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0762`.
|
||||
48
tests/ui/nll/ice-106874.rs
Normal file
48
tests/ui/nll/ice-106874.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// issue: rust-lang/rust#106874
|
||||
// ICE BoundUniversalRegionError
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn func<V, F: Fn(&mut V)>(f: F) -> A<impl X> {
|
||||
A(B(C::new(D::new(move |st| f(st)))))
|
||||
//~^ ERROR implementation of `FnOnce` is not general enough
|
||||
//~| ERROR implementation of `Fn` is not general enough
|
||||
//~| ERROR implementation of `FnOnce` is not general enough
|
||||
//~| ERROR implementation of `FnOnce` is not general enough
|
||||
//~| ERROR implementation of `Fn` is not general enough
|
||||
//~| ERROR implementation of `FnOnce` is not general enough
|
||||
//~| ERROR implementation of `Fn` is not general enough
|
||||
//~| ERROR implementation of `FnOnce` is not general enough
|
||||
//~| ERROR higher-ranked subtype error
|
||||
//~| ERROR higher-ranked subtype error
|
||||
}
|
||||
|
||||
trait X {}
|
||||
trait Y {
|
||||
type V;
|
||||
}
|
||||
|
||||
struct A<T>(T);
|
||||
|
||||
struct B<T>(Rc<T>);
|
||||
impl<T> X for B<T> {}
|
||||
|
||||
struct C<T: Y>(T::V);
|
||||
impl<T: Y> C<T> {
|
||||
fn new(_: T) -> Rc<Self> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
struct D<V, F>(F, PhantomData<fn(&mut V)>);
|
||||
|
||||
impl<V, F> D<V, F> {
|
||||
fn new(_: F) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl<V, F: Fn(&mut V)> Y for D<V, F> {
|
||||
type V = V;
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
90
tests/ui/nll/ice-106874.stderr
Normal file
90
tests/ui/nll/ice-106874.stderr
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:5
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`...
|
||||
= note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:5
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`...
|
||||
= note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:9
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:9
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:9
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/ice-106874.rs:8:41
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/ice-106874.rs:8:41
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
@ -5,5 +5,5 @@ fn main() {
|
|||
//~| HELP if you meant to write a byte string literal, use double quotes
|
||||
let _bar = 'hello';
|
||||
//~^ ERROR character literal may only contain one codepoint
|
||||
//~| HELP if you meant to write a `str` literal, use double quotes
|
||||
//~| HELP if you meant to write a string literal, use double quotes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | let _foo = b'hello\0';
|
|||
help: if you meant to write a byte string literal, use double quotes
|
||||
|
|
||||
LL | let _foo = b"hello\0";
|
||||
| ~~~~~~~~~~
|
||||
| ~~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/issue-64732.rs:6:16
|
||||
|
|
@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
|
|||
LL | let _bar = 'hello';
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _bar = "hello";
|
||||
| ~~~~~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ fn main() {
|
|||
let _spade = "♠️";
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
//~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
|
||||
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||
//~| HELP: if you meant to write a string literal, use double quotes
|
||||
|
||||
let _s = "ṩ̂̊";
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
//~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
||||
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||
//~| HELP: if you meant to write a string literal, use double quotes
|
||||
|
||||
let _a = 'Å';
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ fn main() {
|
|||
let _spade = '♠️';
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
//~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
|
||||
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||
//~| HELP: if you meant to write a string literal, use double quotes
|
||||
|
||||
let _s = 'ṩ̂̊';
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
//~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
||||
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||
//~| HELP: if you meant to write a string literal, use double quotes
|
||||
|
||||
let _a = 'Å';
|
||||
//~^ ERROR: character literal may only contain one codepoint
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ note: this `♠` is followed by the combining mark `\u{fe0f}`
|
|||
|
|
||||
LL | let _spade = '♠️';
|
||||
| ^
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _spade = "♠️";
|
||||
| ~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/unicode-character-literal.rs:12:14
|
||||
|
|
@ -25,10 +25,10 @@ note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
|||
|
|
||||
LL | let _s = 'ṩ̂̊';
|
||||
| ^
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | let _s = "ṩ̂̊";
|
||||
| ~~~
|
||||
| ~ ~
|
||||
|
||||
error: character literal may only contain one codepoint
|
||||
--> $DIR/unicode-character-literal.rs:17:14
|
||||
|
|
|
|||
15
tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs
Normal file
15
tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// issue: rust-lang/rust#105047
|
||||
// ICE raw ptr comparison should already be caught in the trait systems
|
||||
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
const RCZ: *const i32 = &raw const *&0;
|
||||
|
||||
const fn f() {
|
||||
if let RCZ = &raw const *&0 { }
|
||||
//~^ WARN function pointers and raw pointers not derived from integers in patterns
|
||||
//~| ERROR pointers cannot be reliably compared during const eval
|
||||
//~| WARN this was previously accepted by the compiler but is being phased out
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
31
tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr
Normal file
31
tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/const-eval-compare-ice-105047.rs:9:12
|
||||
|
|
||||
LL | if let RCZ = &raw const *&0 { }
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
error: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/const-eval-compare-ice-105047.rs:9:12
|
||||
|
|
||||
LL | if let RCZ = &raw const *&0 { }
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/const-eval-compare-ice-105047.rs:9:12
|
||||
|
|
||||
LL | if let RCZ = &raw const *&0 { }
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
|
||||
= note: `#[warn(pointer_structural_match)]` on by default
|
||||
|
||||
28
tests/ui/specialization/broken-mir-drop-glue-107228.rs
Normal file
28
tests/ui/specialization/broken-mir-drop-glue-107228.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// issue: rust-lang/rust#107228
|
||||
// ICE broken MIR in DropGlue
|
||||
//@ compile-flags: -Zvalidate-mir
|
||||
//@ check-pass
|
||||
|
||||
#![feature(specialization)]
|
||||
#![crate_type="lib"]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub(crate) trait SpecTrait {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<C> SpecTrait for C {
|
||||
default type Assoc = Vec<Self>;
|
||||
}
|
||||
|
||||
pub(crate) struct AssocWrap<C: SpecTrait> {
|
||||
_assoc: C::Assoc,
|
||||
}
|
||||
|
||||
fn instantiate<C: SpecTrait>() -> AssocWrap<C> {
|
||||
loop {}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
instantiate::<()>();
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
|
|||
LL | println!('●●');
|
||||
| ^^^^
|
||||
|
|
||||
help: if you meant to write a `str` literal, use double quotes
|
||||
help: if you meant to write a string literal, use double quotes
|
||||
|
|
||||
LL | println!("●●");
|
||||
| ~~~~
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
28
tests/ui/traits/next-solver/dont-canonicalize-re-error.rs
Normal file
28
tests/ui/traits/next-solver/dont-canonicalize-re-error.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
|
||||
trait Tr<'a> {}
|
||||
|
||||
// Fulfillment in the new solver relies on an invariant to hold: Either
|
||||
// `has_changed` is true, or computing a goal's certainty is idempotent.
|
||||
// This isn't true for `ReError`, which we used to pass through in the
|
||||
// canonicalizer even on input mode, which can cause a goal to go from
|
||||
// ambig => pass, but we don't consider `has_changed` when the response
|
||||
// only contains region constraints (since we usually uniquify regions).
|
||||
//
|
||||
// In this test:
|
||||
// Implicit negative coherence tries to prove `W<?0>: Constrain<'?1>`,
|
||||
// which will then match with the impl below. This constrains `'?1` to
|
||||
// `ReError`, but still bails w/ ambiguity bc we can't prove `?0: Sized`.
|
||||
// Then, when we recompute the goal `W<?0>: Constrain<'error>`, when
|
||||
// collecting ambiguities and overflows, we end up assembling a default
|
||||
// error candidate w/o ambiguity, which causes the goal to pass, and ICE.
|
||||
impl<'a, A: ?Sized> Tr<'a> for W<A> {}
|
||||
struct W<A: ?Sized>(A);
|
||||
impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
|
||||
//~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>`
|
||||
|
||||
trait Constrain<'a> {}
|
||||
impl<A: Sized> Constrain<'missing> for W<A> {}
|
||||
//~^ ERROR use of undeclared lifetime name `'missing`
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
error[E0261]: use of undeclared lifetime name `'missing`
|
||||
--> $DIR/dont-canonicalize-re-error.rs:25:26
|
||||
|
|
||||
LL | impl<A: Sized> Constrain<'missing> for W<A> {}
|
||||
| - ^^^^^^^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'missing` here: `'missing,`
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>`
|
||||
--> $DIR/dont-canonicalize-re-error.rs:21:1
|
||||
|
|
||||
LL | impl<'a, A: ?Sized> Tr<'a> for W<A> {}
|
||||
| ----------------------------------- first implementation here
|
||||
LL | struct W<A: ?Sized>(A);
|
||||
LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0261.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
trait FromResidual<R = <Self as Try>::Residual> {
|
||||
fn from_residual(residual: R) -> Self;
|
||||
}
|
||||
|
||||
trait Try {
|
||||
type Residual;
|
||||
}
|
||||
|
||||
fn w<'a, T: 'a, F: Fn(&'a T)>() {
|
||||
let b: &dyn FromResidual = &();
|
||||
//~^ ERROR: the trait `FromResidual` cannot be made into an object
|
||||
//~| ERROR: the trait `FromResidual` cannot be made into an object
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
error[E0038]: the trait `FromResidual` cannot be made into an object
|
||||
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17
|
||||
|
|
||||
LL | let b: &dyn FromResidual = &();
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
|
||||
|
||||
error[E0038]: the trait `FromResidual` cannot be made into an object
|
||||
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12
|
||||
|
|
||||
LL | let b: &dyn FromResidual = &();
|
||||
| ^^^^^^^^^^^^^^^^^ `FromResidual` cannot be made into an object
|
||||
|
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
|
||||
|
|
||||
LL | trait FromResidual<R = <Self as Try>::Residual> {
|
||||
| ------------ this trait cannot be made into an object...
|
||||
LL | fn from_residual(residual: R) -> Self;
|
||||
| ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter
|
||||
help: consider turning `from_residual` into a method by giving it a `&self` argument
|
||||
|
|
||||
LL | fn from_residual(&self, residual: R) -> Self;
|
||||
| ++++++
|
||||
help: alternatively, consider constraining `from_residual` so it does not apply to trait objects
|
||||
|
|
||||
LL | fn from_residual(residual: R) -> Self where Self: Sized;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// issue: rust-lang/rust#99945
|
||||
// ICE Failed to normalize
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Widget<E> {
|
||||
type State;
|
||||
|
||||
fn make_state(&self) -> Self::State;
|
||||
}
|
||||
|
||||
impl<E> Widget<E> for () {
|
||||
type State = ();
|
||||
|
||||
fn make_state(&self) -> Self::State {}
|
||||
}
|
||||
|
||||
struct StatefulWidget<F>(F);
|
||||
|
||||
type StateWidget<'a> = impl Widget<&'a ()>;
|
||||
|
||||
impl<F: for<'a> Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget<F> {
|
||||
type State = ();
|
||||
|
||||
fn make_state(&self) -> Self::State {}
|
||||
}
|
||||
|
||||
fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
|
||||
StatefulWidget(build)
|
||||
//~^ ERROR expected generic lifetime parameter, found `'a`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
new_stateful_widget(|_| ()).make_state();
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/failed-to-normalize-ice-99945.rs:34:29
|
||||
|
|
||||
LL | type StateWidget<'a> = impl Widget<&'a ()>;
|
||||
| ------------------- the expected opaque type
|
||||
...
|
||||
LL | new_stateful_widget(|_| ()).make_state();
|
||||
| ^^ expected opaque type, found `()`
|
||||
|
|
||||
= note: expected opaque type `StateWidget<'_>`
|
||||
found unit type `()`
|
||||
|
||||
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||
--> $DIR/failed-to-normalize-ice-99945.rs:29:5
|
||||
|
|
||||
LL | type StateWidget<'a> = impl Widget<&'a ()>;
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
...
|
||||
LL | StatefulWidget(build)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0792.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue