Auto merge of #150912 - matthiaskrgr:rollup-SHXgjYS, r=matthiaskrgr
Rollup of 11 pull requests Successful merges: - rust-lang/rust#150269 (Remove inactive nvptx maintainer) - rust-lang/rust#150713 (mgca: Type-check fields of struct expr const args) - rust-lang/rust#150765 (rustc_parse_format: improve error for missing `:` before `?` in format args) - rust-lang/rust#150847 (Fix broken documentation links to SipHash) - rust-lang/rust#150867 (rustdoc_json: Remove one call to `std::mem::take` in `after_krate`) - rust-lang/rust#150872 (Fix some loop block coercion diagnostics) - rust-lang/rust#150874 (Ignore `rustc-src-gpl` in fast try builds) - rust-lang/rust#150875 (Refactor artifact keep mode in bootstrap) - rust-lang/rust#150876 (Mention that `rustc_codegen_gcc` is a subtree in `rustc-dev-guide`) - rust-lang/rust#150882 (Supress unused_parens lint for guard patterns) - rust-lang/rust#150884 (Update bors email in CI postprocessing step) Failed merges: - rust-lang/rust#150869 (Emit error instead of delayed bug when meeting mismatch type for const tuple) r? @ghost
This commit is contained in:
commit
ad04f76d84
34 changed files with 495 additions and 123 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -289,7 +289,7 @@ jobs:
|
|||
fi
|
||||
|
||||
# Get closest bors merge commit
|
||||
PARENT_COMMIT=`git rev-list --author='bors <bors@rust-lang.org>' -n1 --first-parent HEAD^1`
|
||||
PARENT_COMMIT=`git rev-list --author='122020455+rust-bors\[bot\]@users.noreply.github.com' -n1 --first-parent HEAD^1`
|
||||
|
||||
./build/citool/debug/citool postprocess-metrics \
|
||||
--job-name ${CI_JOB_NAME} \
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ builtin_macros_expected_other = expected operand, {$is_inline_asm ->
|
|||
|
||||
builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently
|
||||
|
||||
builtin_macros_format_add_missing_colon = add a colon before the format specifier
|
||||
|
||||
builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
|
||||
.label1 = previously here
|
||||
.label2 = duplicate argument
|
||||
|
|
|
|||
|
|
@ -643,6 +643,15 @@ pub(crate) enum InvalidFormatStringSuggestion {
|
|||
span: Span,
|
||||
replacement: String,
|
||||
},
|
||||
#[suggestion(
|
||||
builtin_macros_format_add_missing_colon,
|
||||
code = ":?",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
AddMissingColon {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -329,6 +329,10 @@ fn make_format_args(
|
|||
replacement,
|
||||
});
|
||||
}
|
||||
parse::Suggestion::AddMissingColon(span) => {
|
||||
let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
|
||||
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::AddMissingColon { span });
|
||||
}
|
||||
}
|
||||
let guar = ecx.dcx().emit_err(e);
|
||||
return ExpandResult::Ready(Err(guar));
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ use rustc_middle::ty::adjustment::{
|
|||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
|
||||
use rustc_span::{BytePos, DUMMY_SP, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
|
||||
use rustc_trait_selection::solve::{Certainty, Goal, NoSolution};
|
||||
|
|
@ -1828,10 +1828,9 @@ impl<'tcx> CoerceMany<'tcx> {
|
|||
// If the block is from an external macro or try (`?`) desugaring, then
|
||||
// do not suggest adding a semicolon, because there's nowhere to put it.
|
||||
// See issues #81943 and #87051.
|
||||
&& matches!(
|
||||
cond_expr.span.desugaring_kind(),
|
||||
None | Some(DesugaringKind::WhileLoop)
|
||||
)
|
||||
// Similarly, if the block is from a loop desugaring, then also do not
|
||||
// suggest adding a semicolon. See issue #150850.
|
||||
&& cond_expr.span.desugaring_kind().is_none()
|
||||
&& !cond_expr.span.in_external_macro(fcx.tcx.sess.source_map())
|
||||
&& !matches!(
|
||||
cond_expr.kind,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
|||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
|
||||
GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
|
||||
WherePredicateKind, expr_needs_parens, is_range_literal,
|
||||
GenericBound, HirId, LoopSource, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind,
|
||||
TyKind, WherePredicateKind, expr_needs_parens, is_range_literal,
|
||||
};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_hir_analysis::suggest_impl_trait;
|
||||
|
|
@ -1170,15 +1170,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
let found = self.resolve_vars_if_possible(found);
|
||||
|
||||
let in_loop = self.is_loop(id)
|
||||
|| self
|
||||
.tcx
|
||||
let innermost_loop = if self.is_loop(id) {
|
||||
Some(self.tcx.hir_node(id))
|
||||
} else {
|
||||
self.tcx
|
||||
.hir_parent_iter(id)
|
||||
.take_while(|(_, node)| {
|
||||
// look at parents until we find the first body owner
|
||||
node.body_id().is_none()
|
||||
})
|
||||
.any(|(parent_id, _)| self.is_loop(parent_id));
|
||||
.find_map(|(parent_id, node)| self.is_loop(parent_id).then_some(node))
|
||||
};
|
||||
let can_break_with_value = innermost_loop.is_some_and(|node| {
|
||||
matches!(
|
||||
node,
|
||||
Node::Expr(Expr { kind: ExprKind::Loop(_, _, LoopSource::Loop, ..), .. })
|
||||
)
|
||||
});
|
||||
|
||||
let in_local_statement = self.is_local_statement(id)
|
||||
|| self
|
||||
|
|
@ -1186,7 +1194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.hir_parent_iter(id)
|
||||
.any(|(parent_id, _)| self.is_local_statement(parent_id));
|
||||
|
||||
if in_loop && in_local_statement {
|
||||
if can_break_with_value && in_local_statement {
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to break the loop with this value",
|
||||
vec![
|
||||
|
|
|
|||
|
|
@ -1190,6 +1190,8 @@ impl UnusedParens {
|
|||
// `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
|
||||
// that if there are unnecessary parens they serve a purpose of readability.
|
||||
PatKind::Range(..) => return,
|
||||
// Parentheses may be necessary to disambiguate precedence in guard patterns.
|
||||
PatKind::Guard(..) => return,
|
||||
// Avoid `p0 | .. | pn` if we should.
|
||||
PatKind::Or(..) if avoid_or => return,
|
||||
// Avoid `mut x` and `mut x @ p` if we should:
|
||||
|
|
|
|||
|
|
@ -191,8 +191,7 @@ impl<'tcx> Value<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Destructures array, ADT or tuple constants into the constants
|
||||
/// of their fields.
|
||||
/// Destructures ADT constants into the constants of their fields.
|
||||
pub fn destructure_adt_const(&self) -> ty::DestructuredAdtConst<'tcx> {
|
||||
let fields = self.to_branch();
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@ pub enum Suggestion {
|
|||
/// `format!("{foo:?x}")` -> `format!("{foo:x?}")`
|
||||
/// `format!("{foo:?X}")` -> `format!("{foo:X?}")`
|
||||
ReorderFormatParameter(Range<usize>, String),
|
||||
/// Add missing colon:
|
||||
/// `format!("{foo?}")` -> `format!("{foo:?}")`
|
||||
AddMissingColon(Range<usize>),
|
||||
}
|
||||
|
||||
/// The parser structure for interpreting the input format string. This is
|
||||
|
|
@ -453,10 +456,11 @@ impl<'input> Parser<'input> {
|
|||
suggestion: Suggestion::None,
|
||||
});
|
||||
|
||||
if let Some((_, _, c)) = self.peek() {
|
||||
match c {
|
||||
'?' => self.suggest_format_debug(),
|
||||
'<' | '^' | '>' => self.suggest_format_align(c),
|
||||
if let (Some((_, _, c)), Some((_, _, nc))) = (self.peek(), self.peek_ahead()) {
|
||||
match (c, nc) {
|
||||
('?', '}') => self.missing_colon_before_debug_formatter(),
|
||||
('?', _) => self.suggest_format_debug(),
|
||||
('<' | '^' | '>', _) => self.suggest_format_align(c),
|
||||
_ => self.suggest_positional_arg_instead_of_captured_arg(arg),
|
||||
}
|
||||
}
|
||||
|
|
@ -849,6 +853,23 @@ impl<'input> Parser<'input> {
|
|||
}
|
||||
}
|
||||
|
||||
fn missing_colon_before_debug_formatter(&mut self) {
|
||||
if let Some((range, _)) = self.consume_pos('?') {
|
||||
let span = range.clone();
|
||||
self.errors.insert(
|
||||
0,
|
||||
ParseError {
|
||||
description: "expected `}`, found `?`".to_owned(),
|
||||
note: Some(format!("to print `{{`, you can escape it using `{{{{`",)),
|
||||
label: "expected `:` before `?` to format with `Debug`".to_owned(),
|
||||
span: range,
|
||||
secondary_label: None,
|
||||
suggestion: Suggestion::AddMissingColon(span),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_format_align(&mut self, alignment: char) {
|
||||
if let Some((range, _)) = self.consume_pos(alignment) {
|
||||
self.errors.insert(
|
||||
|
|
|
|||
|
|
@ -1051,7 +1051,53 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
| ty::ConstKind::Placeholder(..) => {
|
||||
// These variants are trivially WF, so nothing to do here.
|
||||
}
|
||||
ty::ConstKind::Value(..) => {
|
||||
ty::ConstKind::Value(val) => {
|
||||
// FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased
|
||||
if tcx.features().min_generic_const_args() {
|
||||
match val.ty.kind() {
|
||||
ty::Adt(adt_def, args) => {
|
||||
let adt_val = val.destructure_adt_const();
|
||||
let variant_def = adt_def.variant(adt_val.variant);
|
||||
let cause = self.cause(ObligationCauseCode::WellFormed(None));
|
||||
self.out.extend(variant_def.fields.iter().zip(adt_val.fields).map(
|
||||
|(field_def, &field_val)| {
|
||||
let field_ty =
|
||||
tcx.type_of(field_def.did).instantiate(tcx, args);
|
||||
let predicate = ty::PredicateKind::Clause(
|
||||
ty::ClauseKind::ConstArgHasType(field_val, field_ty),
|
||||
);
|
||||
traits::Obligation::with_depth(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
predicate,
|
||||
)
|
||||
},
|
||||
));
|
||||
}
|
||||
ty::Tuple(field_tys) => {
|
||||
let field_vals = val.to_branch();
|
||||
let cause = self.cause(ObligationCauseCode::WellFormed(None));
|
||||
self.out.extend(field_tys.iter().zip(field_vals).map(
|
||||
|(field_ty, &field_val)| {
|
||||
let predicate = ty::PredicateKind::Clause(
|
||||
ty::ClauseKind::ConstArgHasType(field_val, field_ty),
|
||||
);
|
||||
traits::Obligation::with_depth(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
predicate,
|
||||
)
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Enforce that values are structurally-matchable.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{cmp, ptr};
|
|||
/// This is currently the default hashing function used by standard library
|
||||
/// (e.g., `collections::HashMap` uses it by default).
|
||||
///
|
||||
/// See: <https://131002.net/siphash>
|
||||
/// See: <https://github.com/veorq/SipHash>
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
@ -21,7 +21,7 @@ pub struct SipHasher13 {
|
|||
|
||||
/// An implementation of SipHash 2-4.
|
||||
///
|
||||
/// See: <https://131002.net/siphash/>
|
||||
/// See: <https://github.com/veorq/SipHash>
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
@ -31,7 +31,7 @@ struct SipHasher24 {
|
|||
|
||||
/// An implementation of SipHash 2-4.
|
||||
///
|
||||
/// See: <https://131002.net/siphash/>
|
||||
/// See: <https://github.com/veorq/SipHash>
|
||||
///
|
||||
/// SipHash is a general-purpose hashing function: it runs at a good
|
||||
/// speed (competitive with Spooky and City) and permits strong _keyed_
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use std::fs;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::core::build_steps::compile::{
|
||||
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
|
||||
ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
|
||||
std_crates_for_run_make,
|
||||
};
|
||||
use crate::core::build_steps::tool;
|
||||
use crate::core::build_steps::tool::{
|
||||
|
|
@ -111,8 +112,7 @@ impl Step for Std {
|
|||
builder.config.free_args.clone(),
|
||||
&check_stamp,
|
||||
vec![],
|
||||
true,
|
||||
false,
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
|
||||
drop(_guard);
|
||||
|
|
@ -148,7 +148,14 @@ impl Step for Std {
|
|||
build_compiler,
|
||||
target,
|
||||
);
|
||||
run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
builder.config.free_args.clone(),
|
||||
&stamp,
|
||||
vec![],
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
check_stamp
|
||||
}
|
||||
|
||||
|
|
@ -368,7 +375,14 @@ impl Step for Rustc {
|
|||
let stamp =
|
||||
build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
|
||||
|
||||
run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
builder.config.free_args.clone(),
|
||||
&stamp,
|
||||
vec![],
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
|
||||
stamp
|
||||
}
|
||||
|
|
@ -568,7 +582,14 @@ impl Step for CraneliftCodegenBackend {
|
|||
)
|
||||
.with_prefix("check");
|
||||
|
||||
run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
builder.config.free_args.clone(),
|
||||
&stamp,
|
||||
vec![],
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<StepMetadata> {
|
||||
|
|
@ -639,7 +660,14 @@ impl Step for GccCodegenBackend {
|
|||
)
|
||||
.with_prefix("check");
|
||||
|
||||
run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
builder.config.free_args.clone(),
|
||||
&stamp,
|
||||
vec![],
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<StepMetadata> {
|
||||
|
|
@ -777,7 +805,14 @@ fn run_tool_check_step(
|
|||
.with_prefix(&format!("{display_name}-check"));
|
||||
|
||||
let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
|
||||
run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
builder.config.free_args.clone(),
|
||||
&stamp,
|
||||
vec![],
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
}
|
||||
|
||||
tool_check_step!(Rustdoc {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use build_helper::exit;
|
||||
|
||||
use super::compile::{run_cargo, rustc_cargo, std_cargo};
|
||||
use super::compile::{ArtifactKeepMode, run_cargo, rustc_cargo, std_cargo};
|
||||
use super::tool::{SourceType, prepare_tool_cargo};
|
||||
use crate::builder::{Builder, ShouldRun};
|
||||
use crate::core::build_steps::check::{CompilerForCheck, prepare_compiler_for_check};
|
||||
|
|
@ -214,8 +214,7 @@ impl Step for Std {
|
|||
lint_args(builder, &self.config, IGNORED_RULES_FOR_STD_AND_RUSTC),
|
||||
&build_stamp::libstd_stamp(builder, build_compiler, target),
|
||||
vec![],
|
||||
true,
|
||||
false,
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -309,8 +308,7 @@ impl Step for Rustc {
|
|||
lint_args(builder, &self.config, IGNORED_RULES_FOR_STD_AND_RUSTC),
|
||||
&build_stamp::librustc_stamp(builder, build_compiler, target),
|
||||
vec![],
|
||||
true,
|
||||
false,
|
||||
ArtifactKeepMode::OnlyRmeta,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -380,7 +378,7 @@ impl Step for CodegenGcc {
|
|||
.with_prefix("rustc_codegen_gcc-check");
|
||||
|
||||
let args = lint_args(builder, &self.config, &[]);
|
||||
run_cargo(builder, cargo, args.clone(), &stamp, vec![], true, false);
|
||||
run_cargo(builder, cargo, args.clone(), &stamp, vec![], ArtifactKeepMode::OnlyRmeta);
|
||||
|
||||
// Same but we disable the features enabled by default.
|
||||
let mut cargo = prepare_tool_cargo(
|
||||
|
|
@ -396,7 +394,7 @@ impl Step for CodegenGcc {
|
|||
self.build_compiler.configure_cargo(&mut cargo);
|
||||
println!("Now running clippy on `rustc_codegen_gcc` with `--no-default-features`");
|
||||
cargo.arg("--no-default-features");
|
||||
run_cargo(builder, cargo, args, &stamp, vec![], true, false);
|
||||
run_cargo(builder, cargo, args, &stamp, vec![], ArtifactKeepMode::OnlyRmeta);
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<StepMetadata> {
|
||||
|
|
@ -478,8 +476,7 @@ macro_rules! lint_any {
|
|||
lint_args(builder, &self.config, &[]),
|
||||
&stamp,
|
||||
vec![],
|
||||
true,
|
||||
false,
|
||||
ArtifactKeepMode::OnlyRmeta
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -296,8 +296,11 @@ impl Step for Std {
|
|||
vec![],
|
||||
&stamp,
|
||||
target_deps,
|
||||
self.is_for_mir_opt_tests, // is_check
|
||||
false,
|
||||
if self.is_for_mir_opt_tests {
|
||||
ArtifactKeepMode::OnlyRmeta
|
||||
} else {
|
||||
ArtifactKeepMode::OnlyRlib
|
||||
},
|
||||
);
|
||||
|
||||
builder.ensure(StdLink::from_std(
|
||||
|
|
@ -1167,14 +1170,28 @@ impl Step for Rustc {
|
|||
target,
|
||||
);
|
||||
let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
|
||||
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
vec![],
|
||||
&stamp,
|
||||
vec![],
|
||||
false,
|
||||
true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files.
|
||||
ArtifactKeepMode::Custom(Box::new(|filename| {
|
||||
if filename.contains("jemalloc_sys")
|
||||
|| filename.contains("rustc_public_bridge")
|
||||
|| filename.contains("rustc_public")
|
||||
{
|
||||
// jemalloc_sys and rustc_public_bridge are not linked into librustc_driver.so,
|
||||
// so we need to distribute them as rlib to be able to use them.
|
||||
filename.ends_with(".rlib")
|
||||
} else {
|
||||
// Distribute the rest of the rustc crates as rmeta files only to reduce
|
||||
// the tarball sizes by about 50%. The object files are linked into
|
||||
// librustc_driver.so, so it is still possible to link against them.
|
||||
filename.ends_with(".rmeta")
|
||||
}
|
||||
})),
|
||||
);
|
||||
|
||||
let target_root_dir = stamp.path().parent().unwrap();
|
||||
|
|
@ -1714,7 +1731,7 @@ impl Step for GccCodegenBackend {
|
|||
|
||||
let _guard =
|
||||
builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);
|
||||
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
|
||||
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
|
||||
|
||||
GccCodegenBackendOutput {
|
||||
stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
|
||||
|
|
@ -1790,7 +1807,7 @@ impl Step for CraneliftCodegenBackend {
|
|||
build_compiler,
|
||||
target,
|
||||
);
|
||||
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
|
||||
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
|
||||
write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
|
||||
}
|
||||
|
||||
|
|
@ -2620,14 +2637,26 @@ pub fn add_to_sysroot(
|
|||
}
|
||||
}
|
||||
|
||||
/// Specifies which rlib/rmeta artifacts outputted by Cargo should be put into the resulting
|
||||
/// build stamp, and thus be included in dist archives and copied into sysroots by default.
|
||||
/// Note that some kinds of artifacts are copied automatically (e.g. native libraries).
|
||||
pub enum ArtifactKeepMode {
|
||||
/// Only keep .rlib files, ignore .rmeta files
|
||||
OnlyRlib,
|
||||
/// Only keep .rmeta files, ignore .rlib files
|
||||
OnlyRmeta,
|
||||
/// Custom logic for keeping an artifact
|
||||
/// It receives the filename of an artifact, and returns true if it should be kept.
|
||||
Custom(Box<dyn Fn(&str) -> bool>),
|
||||
}
|
||||
|
||||
pub fn run_cargo(
|
||||
builder: &Builder<'_>,
|
||||
cargo: Cargo,
|
||||
tail_args: Vec<String>,
|
||||
stamp: &BuildStamp,
|
||||
additional_target_deps: Vec<(PathBuf, DependencyType)>,
|
||||
is_check: bool,
|
||||
rlib_only_metadata: bool,
|
||||
artifact_keep_mode: ArtifactKeepMode,
|
||||
) -> Vec<PathBuf> {
|
||||
// `target_root_dir` looks like $dir/$target/release
|
||||
let target_root_dir = stamp.path().parent().unwrap();
|
||||
|
|
@ -2661,36 +2690,20 @@ pub fn run_cargo(
|
|||
};
|
||||
for filename in filenames_vec {
|
||||
// Skip files like executables
|
||||
let mut keep = false;
|
||||
if filename.ends_with(".lib")
|
||||
let keep = if filename.ends_with(".lib")
|
||||
|| filename.ends_with(".a")
|
||||
|| is_debug_info(&filename)
|
||||
|| is_dylib(Path::new(&*filename))
|
||||
{
|
||||
// Always keep native libraries, rust dylibs and debuginfo
|
||||
keep = true;
|
||||
}
|
||||
if is_check && filename.ends_with(".rmeta") {
|
||||
// During check builds we need to keep crate metadata
|
||||
keep = true;
|
||||
} else if rlib_only_metadata {
|
||||
if filename.contains("jemalloc_sys")
|
||||
|| filename.contains("rustc_public_bridge")
|
||||
|| filename.contains("rustc_public")
|
||||
{
|
||||
// jemalloc_sys and rustc_public_bridge are not linked into librustc_driver.so,
|
||||
// so we need to distribute them as rlib to be able to use them.
|
||||
keep |= filename.ends_with(".rlib");
|
||||
} else {
|
||||
// Distribute the rest of the rustc crates as rmeta files only to reduce
|
||||
// the tarball sizes by about 50%. The object files are linked into
|
||||
// librustc_driver.so, so it is still possible to link against them.
|
||||
keep |= filename.ends_with(".rmeta");
|
||||
}
|
||||
true
|
||||
} else {
|
||||
// In all other cases keep all rlibs
|
||||
keep |= filename.ends_with(".rlib");
|
||||
}
|
||||
match &artifact_keep_mode {
|
||||
ArtifactKeepMode::OnlyRlib => filename.ends_with(".rlib"),
|
||||
ArtifactKeepMode::OnlyRmeta => filename.ends_with(".rmeta"),
|
||||
ArtifactKeepMode::Custom(func) => func(&filename),
|
||||
}
|
||||
};
|
||||
|
||||
if !keep {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::{env, fs, iter};
|
|||
|
||||
use build_helper::exit;
|
||||
|
||||
use crate::core::build_steps::compile::{Std, run_cargo};
|
||||
use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo};
|
||||
use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
|
||||
use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
|
||||
use crate::core::build_steps::llvm::get_llvm_version;
|
||||
|
|
@ -2587,7 +2587,8 @@ impl BookTest {
|
|||
let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
|
||||
.with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
|
||||
|
||||
let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
|
||||
let output_paths =
|
||||
run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
|
||||
let directories = output_paths
|
||||
.into_iter()
|
||||
.filter_map(|p| p.parent().map(ToOwned::to_owned))
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ The following external projects are managed using some form of a `subtree`:
|
|||
* [rustfmt](https://github.com/rust-lang/rustfmt)
|
||||
* [rust-analyzer](https://github.com/rust-lang/rust-analyzer)
|
||||
* [rustc_codegen_cranelift](https://github.com/rust-lang/rustc_codegen_cranelift)
|
||||
* [rustc_codegen_gcc](https://github.com/rust-lang/rustc_codegen_gcc)
|
||||
* [rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide)
|
||||
* [compiler-builtins](https://github.com/rust-lang/compiler-builtins)
|
||||
* [stdarch](https://github.com/rust-lang/stdarch)
|
||||
|
|
@ -40,6 +41,7 @@ implement a new tool feature or test, that should happen in one collective rustc
|
|||
* `portable-simd` ([sync script](https://github.com/rust-lang/portable-simd/blob/master/subtree-sync.sh))
|
||||
* `rustfmt`
|
||||
* `rustc_codegen_cranelift` ([sync script](https://github.com/rust-lang/rustc_codegen_cranelift/blob/113af154d459e41b3dc2c5d7d878e3d3a8f33c69/scripts/rustup.sh#L7))
|
||||
* `rustc_codegen_gcc` ([sync guide](https://github.com/rust-lang/rustc_codegen_gcc/blob/master/doc/subtree.md))
|
||||
* Using the [josh](#synchronizing-a-josh-subtree) tool
|
||||
* `miri`
|
||||
* `rust-analyzer`
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ platform.
|
|||
|
||||
## Target maintainers
|
||||
|
||||
[@RDambrosio016](https://github.com/RDambrosio016)
|
||||
[@kjetilkjeka](https://github.com/kjetilkjeka)
|
||||
|
||||
## Requirements
|
||||
|
|
|
|||
|
|
@ -104,22 +104,6 @@ impl<'tcx> JsonRenderer<'tcx> {
|
|||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn serialize_and_write<T: Write>(
|
||||
&self,
|
||||
output_crate: types::Crate,
|
||||
mut writer: BufWriter<T>,
|
||||
path: &str,
|
||||
) -> Result<(), Error> {
|
||||
self.sess().time("rustdoc_json_serialize_and_write", || {
|
||||
try_err!(
|
||||
serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()),
|
||||
path
|
||||
);
|
||||
try_err!(writer.flush(), path);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> JsonRenderer<'tcx> {
|
||||
|
|
@ -252,26 +236,23 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
unreachable!("RUN_ON_MODULE = false, should never call mod_item_in")
|
||||
}
|
||||
|
||||
fn after_krate(mut self) -> Result<(), Error> {
|
||||
fn after_krate(self) -> Result<(), Error> {
|
||||
debug!("Done with crate");
|
||||
|
||||
let e = ExternalCrate { crate_num: LOCAL_CRATE };
|
||||
|
||||
// We've finished using the index, and don't want to clone it, because it is big.
|
||||
let index = std::mem::take(&mut self.index);
|
||||
let sess = self.sess();
|
||||
|
||||
// Note that tcx.rust_target_features is inappropriate here because rustdoc tries to run for
|
||||
// multiple targets: https://github.com/rust-lang/rust/pull/137632
|
||||
//
|
||||
// We want to describe a single target, so pass tcx.sess rather than tcx.
|
||||
let target = conversions::target(self.tcx.sess);
|
||||
let target = conversions::target(sess);
|
||||
|
||||
debug!("Constructing Output");
|
||||
let output_crate = types::Crate {
|
||||
root: self.id_from_item_default(e.def_id().into()),
|
||||
crate_version: self.cache.crate_version.clone(),
|
||||
includes_private: self.cache.document_private,
|
||||
index,
|
||||
paths: self
|
||||
.cache
|
||||
.paths
|
||||
|
|
@ -313,6 +294,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
)
|
||||
})
|
||||
.collect(),
|
||||
// Be careful to not clone the `index`, it is big.
|
||||
index: self.index,
|
||||
target,
|
||||
format_version: types::FORMAT_VERSION,
|
||||
};
|
||||
|
|
@ -323,17 +306,34 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap());
|
||||
p.set_extension("json");
|
||||
|
||||
self.serialize_and_write(
|
||||
serialize_and_write(
|
||||
sess,
|
||||
output_crate,
|
||||
try_err!(File::create_buffered(&p), p),
|
||||
&p.display().to_string(),
|
||||
)
|
||||
} else {
|
||||
self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "<stdout>")
|
||||
serialize_and_write(sess, output_crate, BufWriter::new(stdout().lock()), "<stdout>")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_and_write<T: Write>(
|
||||
sess: &Session,
|
||||
output_crate: types::Crate,
|
||||
mut writer: BufWriter<T>,
|
||||
path: &str,
|
||||
) -> Result<(), Error> {
|
||||
sess.time("rustdoc_json_serialize_and_write", || {
|
||||
try_err!(
|
||||
serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()),
|
||||
path
|
||||
);
|
||||
try_err!(writer.flush(), path);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
|
||||
//
|
||||
// These assertions are here, not in `src/rustdoc-json-types/lib.rs` where the types are defined,
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ fn main() -> anyhow::Result<()> {
|
|||
"rust-docs-json",
|
||||
"rust-analyzer",
|
||||
"rustc-src",
|
||||
"rustc-src-gpl",
|
||||
"extended",
|
||||
"clippy",
|
||||
"miri",
|
||||
|
|
|
|||
|
|
@ -9,12 +9,8 @@ LL | while true {
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/block-must-not-have-result-while.rs:5:9
|
||||
|
|
||||
LL | / while true {
|
||||
LL | | true
|
||||
| | ^^^^ expected `()`, found `bool`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____- expected this to be `()`
|
||||
LL | true
|
||||
| ^^^^ expected `()`, found `bool`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ fn foo<const N: Option<u32>>() {}
|
|||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
const ASSOC: u32;
|
||||
}
|
||||
|
||||
fn bar<T: Trait, const N: u32>() {
|
||||
|
|
|
|||
26
tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs
Normal file
26
tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#![feature(min_generic_const_args, adt_const_params, unsized_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
fn takes_tuple<const A: (u32, u32)>() {}
|
||||
fn takes_nested_tuple<const A: (u32, (u32, u32))>() {}
|
||||
|
||||
fn generic_caller<T: Trait, const N: usize, const N2: u32>() {
|
||||
takes_tuple::<{ (N, N2) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u32`
|
||||
takes_tuple::<{ (N, T::ASSOC) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u32`
|
||||
//~| ERROR the constant `<T as Trait>::ASSOC` is not of type `u32`
|
||||
|
||||
takes_nested_tuple::<{ (N, (N, N2)) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u32`
|
||||
takes_nested_tuple::<{ (N, (N, T::ASSOC)) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u32`
|
||||
//~| ERROR the constant `<T as Trait>::ASSOC` is not of type `u32`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
error: the constant `N` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:13:21
|
||||
|
|
||||
LL | takes_tuple::<{ (N, N2) }>();
|
||||
| ^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: the constant `N` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:15:21
|
||||
|
|
||||
LL | takes_tuple::<{ (N, T::ASSOC) }>();
|
||||
| ^^^^^^^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: the constant `<T as Trait>::ASSOC` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:15:21
|
||||
|
|
||||
LL | takes_tuple::<{ (N, T::ASSOC) }>();
|
||||
| ^^^^^^^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: the constant `N` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:19:28
|
||||
|
|
||||
LL | takes_nested_tuple::<{ (N, (N, N2)) }>();
|
||||
| ^^^^^^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: the constant `N` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:21:28
|
||||
|
|
||||
LL | takes_nested_tuple::<{ (N, (N, T::ASSOC)) }>();
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: the constant `<T as Trait>::ASSOC` is not of type `u32`
|
||||
--> $DIR/adt_expr_arg_tuple_expr_fail.rs:21:28
|
||||
|
|
||||
LL | takes_nested_tuple::<{ (N, (N, T::ASSOC)) }>();
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
const ASSOC: u32;
|
||||
}
|
||||
|
||||
fn takes_tuple<const A: (u32, u32)>() {}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,38 @@
|
|||
//@ check-pass
|
||||
// FIXME(mgca): This should error
|
||||
|
||||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
#[derive(Eq, PartialEq, std::marker::ConstParamTy)]
|
||||
struct Foo<T> { field: T }
|
||||
struct S1<T> {
|
||||
f1: T,
|
||||
f2: isize,
|
||||
}
|
||||
|
||||
fn accepts<const N: Foo<u8>>() {}
|
||||
#[derive(Eq, PartialEq, std::marker::ConstParamTy)]
|
||||
struct S2<T>(T, isize);
|
||||
|
||||
#[derive(Eq, PartialEq, std::marker::ConstParamTy)]
|
||||
enum En<T> {
|
||||
Var1(bool, T),
|
||||
Var2 { field: i64 },
|
||||
}
|
||||
|
||||
fn accepts_1<const N: S1<u8>>() {}
|
||||
fn accepts_2<const N: S2<u8>>() {}
|
||||
fn accepts_3<const N: En<u8>>() {}
|
||||
|
||||
fn bar<const N: bool>() {
|
||||
// `N` is not of type `u8` but we don't actually check this anywhere yet
|
||||
accepts::<{ Foo::<u8> { field: N }}>();
|
||||
accepts_1::<{ S1::<u8> { f1: N, f2: N } }>();
|
||||
//~^ ERROR the constant `N` is not of type `u8`
|
||||
//~| ERROR the constant `N` is not of type `isize`
|
||||
accepts_2::<{ S2::<u8>(N, N) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u8`
|
||||
//~| ERROR the constant `N` is not of type `isize`
|
||||
accepts_3::<{ En::Var1::<u8>(N, N) }>();
|
||||
//~^ ERROR the constant `N` is not of type `u8`
|
||||
accepts_3::<{ En::Var2::<u8> { field: N } }>();
|
||||
//~^ ERROR the constant `N` is not of type `i64`
|
||||
accepts_3::<{ En::Var2::<u8> { field: const { false } } }>();
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:24:19
|
||||
|
|
||||
LL | accepts_1::<{ S1::<u8> { f1: N, f2: N } }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool`
|
||||
|
||||
error: the constant `N` is not of type `isize`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:24:19
|
||||
|
|
||||
LL | accepts_1::<{ S1::<u8> { f1: N, f2: N } }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool`
|
||||
|
||||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:27:19
|
||||
|
|
||||
LL | accepts_2::<{ S2::<u8>(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^ expected `u8`, found `bool`
|
||||
|
||||
error: the constant `N` is not of type `isize`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:27:19
|
||||
|
|
||||
LL | accepts_2::<{ S2::<u8>(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^ expected `isize`, found `bool`
|
||||
|
||||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:30:19
|
||||
|
|
||||
LL | accepts_3::<{ En::Var1::<u8>(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool`
|
||||
|
||||
error: the constant `N` is not of type `i64`
|
||||
--> $DIR/adt_expr_fields_type_check.rs:32:19
|
||||
|
|
||||
LL | accepts_3::<{ En::Var2::<u8> { field: N } }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `bool`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/adt_expr_fields_type_check.rs:34:51
|
||||
|
|
||||
LL | accepts_3::<{ En::Var2::<u8> { field: const { false } } }>();
|
||||
| ^^^^^ expected `i64`, found `bool`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -9,7 +9,7 @@ struct Foo;
|
|||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
const ASSOC: u32;
|
||||
}
|
||||
|
||||
fn foo<const N: Foo>() {}
|
||||
|
|
@ -27,7 +27,7 @@ fn baz<T: Trait>() {
|
|||
fn main() {}
|
||||
|
||||
fn test_ice_missing_bound<T>() {
|
||||
foo::<{Option::Some::<u32>{0: <T as Trait>::ASSOC}}>();
|
||||
foo::<{ Option::Some::<u32> { 0: <T as Trait>::ASSOC } }>();
|
||||
//~^ ERROR the trait bound `T: Trait` is not satisfied
|
||||
//~| ERROR the constant `Option::<u32>::Some(_)` is not of type `Foo`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ LL | fn foo<const N: Foo>() {}
|
|||
error[E0277]: the trait bound `T: Trait` is not satisfied
|
||||
--> $DIR/printing_valtrees_supports_non_values.rs:30:5
|
||||
|
|
||||
LL | foo::<{Option::Some::<u32>{0: <T as Trait>::ASSOC}}>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
|
||||
LL | foo::<{ Option::Some::<u32> { 0: <T as Trait>::ASSOC } }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T` with trait `Trait`
|
||||
|
|
||||
|
|
@ -34,10 +34,10 @@ LL | fn test_ice_missing_bound<T: Trait>() {
|
|||
| +++++++
|
||||
|
||||
error: the constant `Option::<u32>::Some(_)` is not of type `Foo`
|
||||
--> $DIR/printing_valtrees_supports_non_values.rs:30:12
|
||||
--> $DIR/printing_valtrees_supports_non_values.rs:30:13
|
||||
|
|
||||
LL | foo::<{Option::Some::<u32>{0: <T as Trait>::ASSOC}}>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option<u32>`
|
||||
LL | foo::<{ Option::Some::<u32> { 0: <T as Trait>::ASSOC } }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option<u32>`
|
||||
|
|
||||
note: required by a const generic parameter in `foo`
|
||||
--> $DIR/printing_valtrees_supports_non_values.rs:15:8
|
||||
|
|
|
|||
|
|
@ -83,4 +83,7 @@ raw { \n
|
|||
|
||||
println!(r#"\x7B}\u8 {"#, 1);
|
||||
//~^ ERROR invalid format string: unmatched `}` found
|
||||
|
||||
println!("{x?}, world!",);
|
||||
//~^ ERROR invalid format string: expected `}`, found `?`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,5 +177,16 @@ LL | println!(r#"\x7B}\u8 {"#, 1);
|
|||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: invalid format string: expected `}`, found `?`
|
||||
--> $DIR/format-string-error-2.rs:87:17
|
||||
|
|
||||
LL | println!("{x?}, world!",);
|
||||
| ^
|
||||
| |
|
||||
| expected `:` before `?` to format with `Debug` in format string
|
||||
| help: add a colon before the format specifier: `:?`
|
||||
|
|
||||
= note: to print `{`, you can escape it using `{{`
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
//! Don't suggest breaking with value from `for` or `while` loops
|
||||
//!
|
||||
//! Regression test for https://github.com/rust-lang/rust/issues/150850
|
||||
|
||||
fn returns_i32() -> i32 { 0 }
|
||||
|
||||
fn suggest_breaking_from_loop() {
|
||||
let _ = loop {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
//~| SUGGESTION break
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_for() {
|
||||
let _ = for _ in 0.. {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_while() {
|
||||
let cond = true;
|
||||
let _ = while cond {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_for_nested_in_loop() {
|
||||
let _ = loop {
|
||||
for _ in 0.. {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:9:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^ expected `()`, found `i32`
|
||||
|
|
||||
help: consider using a semicolon here
|
||||
|
|
||||
LL | returns_i32();
|
||||
| +
|
||||
help: you might have meant to break the loop with this value
|
||||
|
|
||||
LL | break returns_i32();
|
||||
| +++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:17:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:25:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:33:13
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//! Guard patterns require parentheses to disambiguate precedence
|
||||
//!
|
||||
//! Regression test for https://github.com/rust-lang/rust/issues/149594
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(guard_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
#![warn(unused_parens)]
|
||||
|
||||
fn main() {
|
||||
let (_ if false) = ();
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
//@ check-pass
|
||||
#![feature(guard_patterns, never_type)]
|
||||
#![expect(incomplete_features, unused_parens)]
|
||||
#![expect(incomplete_features)]
|
||||
#![deny(unreachable_code)]
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue