Auto merge of #113646 - matthiaskrgr:rollup-1q6tmow, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #113353 (Implement selection for `Unsize` for better coercion behavior) - #113553 (Make Placeholder, GeneratorWitness*, Infer and Error unreachable on SMIR rustc_ty_to_ty) - #113598 (Update cargo) - #113603 (Test simd-wide-sum for codegen error) - #113613 (Allow to have `-` in rustdoc-json test file name) - #113615 (llvm-wrapper: adapt for LLVM API change) - #113616 (Fix bootstrap.py uname error) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1b3e686925
18 changed files with 228 additions and 33 deletions
|
@ -636,6 +636,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
|
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
|
||||||
if traits.contains(&trait_pred.def_id()) =>
|
if traits.contains(&trait_pred.def_id()) =>
|
||||||
{
|
{
|
||||||
|
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||||
if unsize_did == trait_pred.def_id() {
|
if unsize_did == trait_pred.def_id() {
|
||||||
let self_ty = trait_pred.self_ty();
|
let self_ty = trait_pred.self_ty();
|
||||||
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
|
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
|
||||||
|
@ -662,7 +663,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
// Uncertain or unimplemented.
|
// Uncertain or unimplemented.
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
if trait_pred.def_id() == unsize_did {
|
if trait_pred.def_id() == unsize_did {
|
||||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
|
||||||
let self_ty = trait_pred.self_ty();
|
let self_ty = trait_pred.self_ty();
|
||||||
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
|
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
|
||||||
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
|
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
|
||||||
|
|
|
@ -667,6 +667,7 @@ LLVMRustOptimize(
|
||||||
assert(!PGOUsePath && !PGOSampleUsePath);
|
assert(!PGOUsePath && !PGOSampleUsePath);
|
||||||
PGOOpt = PGOOptions(PGOGenPath, "", "",
|
PGOOpt = PGOOptions(PGOGenPath, "", "",
|
||||||
#if LLVM_VERSION_GE(17, 0)
|
#if LLVM_VERSION_GE(17, 0)
|
||||||
|
"",
|
||||||
FS,
|
FS,
|
||||||
#endif
|
#endif
|
||||||
PGOOptions::IRInstr, PGOOptions::NoCSAction,
|
PGOOptions::IRInstr, PGOOptions::NoCSAction,
|
||||||
|
@ -675,6 +676,7 @@ LLVMRustOptimize(
|
||||||
assert(!PGOSampleUsePath);
|
assert(!PGOSampleUsePath);
|
||||||
PGOOpt = PGOOptions(PGOUsePath, "", "",
|
PGOOpt = PGOOptions(PGOUsePath, "", "",
|
||||||
#if LLVM_VERSION_GE(17, 0)
|
#if LLVM_VERSION_GE(17, 0)
|
||||||
|
"",
|
||||||
FS,
|
FS,
|
||||||
#endif
|
#endif
|
||||||
PGOOptions::IRUse, PGOOptions::NoCSAction,
|
PGOOptions::IRUse, PGOOptions::NoCSAction,
|
||||||
|
@ -682,6 +684,7 @@ LLVMRustOptimize(
|
||||||
} else if (PGOSampleUsePath) {
|
} else if (PGOSampleUsePath) {
|
||||||
PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
|
PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
|
||||||
#if LLVM_VERSION_GE(17, 0)
|
#if LLVM_VERSION_GE(17, 0)
|
||||||
|
"",
|
||||||
FS,
|
FS,
|
||||||
#endif
|
#endif
|
||||||
PGOOptions::SampleUse, PGOOptions::NoCSAction,
|
PGOOptions::SampleUse, PGOOptions::NoCSAction,
|
||||||
|
@ -689,6 +692,7 @@ LLVMRustOptimize(
|
||||||
} else if (DebugInfoForProfiling) {
|
} else if (DebugInfoForProfiling) {
|
||||||
PGOOpt = PGOOptions("", "", "",
|
PGOOpt = PGOOptions("", "", "",
|
||||||
#if LLVM_VERSION_GE(17, 0)
|
#if LLVM_VERSION_GE(17, 0)
|
||||||
|
"",
|
||||||
FS,
|
FS,
|
||||||
#endif
|
#endif
|
||||||
PGOOptions::NoAction, PGOOptions::NoCSAction,
|
PGOOptions::NoAction, PGOOptions::NoCSAction,
|
||||||
|
|
|
@ -103,12 +103,9 @@ impl<'tcx> Tables<'tcx> {
|
||||||
ty::Ref(_, _, _) => todo!(),
|
ty::Ref(_, _, _) => todo!(),
|
||||||
ty::FnDef(_, _) => todo!(),
|
ty::FnDef(_, _) => todo!(),
|
||||||
ty::FnPtr(_) => todo!(),
|
ty::FnPtr(_) => todo!(),
|
||||||
ty::Placeholder(..) => todo!(),
|
|
||||||
ty::Dynamic(_, _, _) => todo!(),
|
ty::Dynamic(_, _, _) => todo!(),
|
||||||
ty::Closure(_, _) => todo!(),
|
ty::Closure(_, _) => todo!(),
|
||||||
ty::Generator(_, _, _) => todo!(),
|
ty::Generator(_, _, _) => todo!(),
|
||||||
ty::GeneratorWitness(_) => todo!(),
|
|
||||||
ty::GeneratorWitnessMIR(_, _) => todo!(),
|
|
||||||
ty::Never => todo!(),
|
ty::Never => todo!(),
|
||||||
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
|
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
|
||||||
fields.iter().map(|ty| self.intern_ty(ty)).collect(),
|
fields.iter().map(|ty| self.intern_ty(ty)).collect(),
|
||||||
|
@ -116,8 +113,13 @@ impl<'tcx> Tables<'tcx> {
|
||||||
ty::Alias(_, _) => todo!(),
|
ty::Alias(_, _) => todo!(),
|
||||||
ty::Param(_) => todo!(),
|
ty::Param(_) => todo!(),
|
||||||
ty::Bound(_, _) => todo!(),
|
ty::Bound(_, _) => todo!(),
|
||||||
ty::Infer(_) => todo!(),
|
ty::Placeholder(..)
|
||||||
ty::Error(_) => todo!(),
|
| ty::GeneratorWitness(_)
|
||||||
|
| ty::GeneratorWitnessMIR(_, _)
|
||||||
|
| ty::Infer(_)
|
||||||
|
| ty::Error(_) => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||||
use rustc_infer::traits::util::supertraits;
|
use rustc_infer::traits::util::supertraits;
|
||||||
|
@ -11,7 +12,7 @@ use rustc_middle::traits::{
|
||||||
ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
|
ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
|
||||||
ObligationCause, SelectionError,
|
ObligationCause, SelectionError,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource};
|
use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource};
|
||||||
|
@ -113,6 +114,12 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
||||||
),
|
),
|
||||||
) => rematch_object(self, goal, nested_obligations),
|
) => rematch_object(self, goal, nested_obligations),
|
||||||
|
|
||||||
|
(Certainty::Maybe(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Misc))
|
||||||
|
if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) =>
|
||||||
|
{
|
||||||
|
rematch_unsize(self, goal, nested_obligations)
|
||||||
|
}
|
||||||
|
|
||||||
// Technically some builtin impls have nested obligations, but if
|
// Technically some builtin impls have nested obligations, but if
|
||||||
// `Certainty::Yes`, then they should've all been verified and don't
|
// `Certainty::Yes`, then they should've all been verified and don't
|
||||||
// need re-checking.
|
// need re-checking.
|
||||||
|
@ -232,6 +239,9 @@ fn rematch_object<'tcx>(
|
||||||
{
|
{
|
||||||
assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
|
assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
|
||||||
if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.substs.type_at(1).kind() {
|
if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.substs.type_at(1).kind() {
|
||||||
|
// FIXME: We also need to ensure that the source lifetime outlives the
|
||||||
|
// target lifetime. This doesn't matter for codegen, though, and only
|
||||||
|
// *really* matters if the goal's certainty is ambiguous.
|
||||||
(true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty))
|
(true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty))
|
||||||
} else {
|
} else {
|
||||||
bug!()
|
bug!()
|
||||||
|
@ -305,3 +315,136 @@ fn rematch_object<'tcx>(
|
||||||
ImplSource::Object(ImplSourceObjectData { vtable_base, nested })
|
ImplSource::Object(ImplSourceObjectData { vtable_base, nested })
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `Unsize` trait is particularly important to coercion, so we try rematch it.
|
||||||
|
/// NOTE: This must stay in sync with `consider_builtin_unsize_candidate` in trait
|
||||||
|
/// goal assembly in the solver, both for soundness and in order to avoid ICEs.
|
||||||
|
fn rematch_unsize<'tcx>(
|
||||||
|
infcx: &InferCtxt<'tcx>,
|
||||||
|
goal: Goal<'tcx, ty::TraitPredicate<'tcx>>,
|
||||||
|
mut nested: Vec<PredicateObligation<'tcx>>,
|
||||||
|
) -> SelectionResult<'tcx, Selection<'tcx>> {
|
||||||
|
let tcx = infcx.tcx;
|
||||||
|
let a_ty = goal.predicate.self_ty();
|
||||||
|
let b_ty = goal.predicate.trait_ref.substs.type_at(1);
|
||||||
|
|
||||||
|
match (a_ty.kind(), b_ty.kind()) {
|
||||||
|
(_, &ty::Dynamic(data, region, ty::Dyn)) => {
|
||||||
|
// Check that the type implements all of the predicates of the def-id.
|
||||||
|
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||||
|
nested.extend(data.iter().map(|pred| {
|
||||||
|
Obligation::new(
|
||||||
|
infcx.tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
goal.param_env,
|
||||||
|
pred.with_self_ty(tcx, a_ty),
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
// The type must be Sized to be unsized.
|
||||||
|
let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, None);
|
||||||
|
nested.push(Obligation::new(
|
||||||
|
infcx.tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
goal.param_env,
|
||||||
|
ty::TraitRef::new(tcx, sized_def_id, [a_ty]),
|
||||||
|
));
|
||||||
|
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||||
|
nested.push(Obligation::new(
|
||||||
|
infcx.tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
goal.param_env,
|
||||||
|
ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// `[T; n]` -> `[T]` unsizing
|
||||||
|
(&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
|
||||||
|
nested.extend(
|
||||||
|
infcx
|
||||||
|
.at(&ObligationCause::dummy(), goal.param_env)
|
||||||
|
.eq(DefineOpaqueTypes::No, a_elem_ty, b_elem_ty)
|
||||||
|
.expect("expected rematch to succeed")
|
||||||
|
.into_obligations(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
|
||||||
|
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
|
||||||
|
if a_def.is_struct() && a_def.did() == b_def.did() =>
|
||||||
|
{
|
||||||
|
let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
|
||||||
|
// We must be unsizing some type parameters. This also implies
|
||||||
|
// that the struct has a tail field.
|
||||||
|
if unsizing_params.is_empty() {
|
||||||
|
bug!("expected rematch to succeed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let tail_field = a_def
|
||||||
|
.non_enum_variant()
|
||||||
|
.fields
|
||||||
|
.raw
|
||||||
|
.last()
|
||||||
|
.expect("expected unsized ADT to have a tail field");
|
||||||
|
let tail_field_ty = tcx.type_of(tail_field.did);
|
||||||
|
|
||||||
|
let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
|
||||||
|
let b_tail_ty = tail_field_ty.subst(tcx, b_substs);
|
||||||
|
|
||||||
|
// Substitute just the unsizing params from B into A. The type after
|
||||||
|
// this substitution must be equal to B. This is so we don't unsize
|
||||||
|
// unrelated type parameters.
|
||||||
|
let new_a_substs =
|
||||||
|
tcx.mk_substs_from_iter(a_substs.iter().enumerate().map(|(i, a)| {
|
||||||
|
if unsizing_params.contains(i as u32) { b_substs[i] } else { a }
|
||||||
|
}));
|
||||||
|
let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_substs);
|
||||||
|
|
||||||
|
nested.extend(
|
||||||
|
infcx
|
||||||
|
.at(&ObligationCause::dummy(), goal.param_env)
|
||||||
|
.eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
|
||||||
|
.expect("expected rematch to succeed")
|
||||||
|
.into_obligations(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Finally, we require that `TailA: Unsize<TailB>` for the tail field
|
||||||
|
// types.
|
||||||
|
nested.push(Obligation::new(
|
||||||
|
tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
goal.param_env,
|
||||||
|
ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
|
||||||
|
(&ty::Tuple(a_tys), &ty::Tuple(b_tys))
|
||||||
|
if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
|
||||||
|
{
|
||||||
|
let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||||
|
let b_last_ty = b_tys.last().unwrap();
|
||||||
|
|
||||||
|
// Substitute just the tail field of B., and require that they're equal.
|
||||||
|
let unsized_a_ty =
|
||||||
|
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied());
|
||||||
|
nested.extend(
|
||||||
|
infcx
|
||||||
|
.at(&ObligationCause::dummy(), goal.param_env)
|
||||||
|
.eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
|
||||||
|
.expect("expected rematch to succeed")
|
||||||
|
.into_obligations(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Similar to ADTs, require that the rest of the fields are equal.
|
||||||
|
nested.push(Obligation::new(
|
||||||
|
tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
goal.param_env,
|
||||||
|
ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// FIXME: We *could* ICE here if either:
|
||||||
|
// 1. the certainty is `Certainty::Yes`,
|
||||||
|
// 2. we're in codegen (which should mean `Certainty::Yes`).
|
||||||
|
_ => return Ok(None),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(ImplSource::Builtin(nested)))
|
||||||
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ def default_build_triple(verbose):
|
||||||
if uname is None:
|
if uname is None:
|
||||||
return 'x86_64-pc-windows-msvc'
|
return 'x86_64-pc-windows-msvc'
|
||||||
|
|
||||||
kernel, cputype, processor = uname.decode(default_encoding).split()
|
kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2)
|
||||||
|
|
||||||
# The goal here is to come up with the same triple as LLVM would,
|
# The goal here is to come up with the same triple as LLVM would,
|
||||||
# at least for the subset of platforms we're willing to target.
|
# at least for the subset of platforms we're willing to target.
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 45782b6b8afd1da042d45c2daeec9c0744f72cc7
|
Subproject commit 694a579566a9a1482b20aff8a68f0e4edd99bd28
|
|
@ -541,16 +541,15 @@ impl TestProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
|
fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
|
||||||
let check_no_run = |s| {
|
let check_no_run = |s| match (config.mode, s) {
|
||||||
if config.mode != Mode::Ui && config.mode != Mode::Incremental {
|
(Mode::Ui, _) => (),
|
||||||
panic!("`{}` header is only supported in UI and incremental tests", s);
|
(Mode::Codegen, "build-pass") => (),
|
||||||
|
(Mode::Incremental, _) => {
|
||||||
|
if revision.is_some() && !self.revisions.iter().all(|r| r.starts_with("cfail")) {
|
||||||
|
panic!("`{s}` header is only supported in `cfail` incremental tests")
|
||||||
}
|
}
|
||||||
if config.mode == Mode::Incremental
|
|
||||||
&& !revision.map_or(false, |r| r.starts_with("cfail"))
|
|
||||||
&& !self.revisions.iter().all(|r| r.starts_with("cfail"))
|
|
||||||
{
|
|
||||||
panic!("`{}` header is only supported in `cfail` incremental tests", s);
|
|
||||||
}
|
}
|
||||||
|
(mode, _) => panic!("`{s}` header is not supported in `{mode}` tests"),
|
||||||
};
|
};
|
||||||
let pass_mode = if config.parse_name_directive(ln, "check-pass") {
|
let pass_mode = if config.parse_name_directive(ln, "check-pass") {
|
||||||
check_no_run("check-pass");
|
check_no_run("check-pass");
|
||||||
|
@ -559,9 +558,7 @@ impl TestProps {
|
||||||
check_no_run("build-pass");
|
check_no_run("build-pass");
|
||||||
Some(PassMode::Build)
|
Some(PassMode::Build)
|
||||||
} else if config.parse_name_directive(ln, "run-pass") {
|
} else if config.parse_name_directive(ln, "run-pass") {
|
||||||
if config.mode != Mode::Ui {
|
check_no_run("run-pass");
|
||||||
panic!("`run-pass` header is only supported in UI tests")
|
|
||||||
}
|
|
||||||
Some(PassMode::Run)
|
Some(PassMode::Run)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -2752,6 +2752,10 @@ impl<'test> TestCx<'test> {
|
||||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(PassMode::Build) = self.pass_mode() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let output_path = self.output_base_name().with_extension("ll");
|
let output_path = self.output_base_name().with_extension("ll");
|
||||||
let proc_res = self.verify_with_filecheck(&output_path);
|
let proc_res = self.verify_with_filecheck(&output_path);
|
||||||
if !proc_res.status.success() {
|
if !proc_res.status.success() {
|
||||||
|
|
|
@ -15,8 +15,10 @@ impl Cache {
|
||||||
/// Create a new cache, used to read files only once and otherwise store their contents.
|
/// Create a new cache, used to read files only once and otherwise store their contents.
|
||||||
pub fn new(config: &Config) -> Cache {
|
pub fn new(config: &Config) -> Cache {
|
||||||
let root = Path::new(&config.doc_dir);
|
let root = Path::new(&config.doc_dir);
|
||||||
let filename = Path::new(&config.template).file_stem().unwrap();
|
// `filename` needs to replace `-` with `_` to be sure the JSON path will always be valid.
|
||||||
let file_path = root.join(&Path::with_extension(Path::new(filename), "json"));
|
let filename =
|
||||||
|
Path::new(&config.template).file_stem().unwrap().to_str().unwrap().replace('-', "_");
|
||||||
|
let file_path = root.join(&Path::with_extension(Path::new(&filename), "json"));
|
||||||
let content = fs::read_to_string(&file_path).expect("failed to read JSON file");
|
let content = fs::read_to_string(&file_path).expect("failed to read JSON file");
|
||||||
|
|
||||||
Cache {
|
Cache {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
@ -25,7 +26,7 @@ enum ErrorKind {
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct JsonOutput {
|
struct JsonOutput {
|
||||||
path: String,
|
path: PathBuf,
|
||||||
errors: Vec<Error>,
|
errors: Vec<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +46,12 @@ struct Cli {
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let Cli { path, verbose, json_output } = Cli::parse();
|
let Cli { path, verbose, json_output } = Cli::parse();
|
||||||
|
|
||||||
|
// We convert `-` into `_` for the file name to be sure the JSON path will always be correct.
|
||||||
|
let path = Path::new(&path);
|
||||||
|
let filename = path.file_name().unwrap().to_str().unwrap().replace('-', "_");
|
||||||
|
let parent = path.parent().unwrap();
|
||||||
|
let path = parent.join(&filename);
|
||||||
|
|
||||||
let contents = fs::read_to_string(&path)?;
|
let contents = fs::read_to_string(&path)?;
|
||||||
let krate: Crate = serde_json::from_str(&contents)?;
|
let krate: Crate = serde_json::from_str(&contents)?;
|
||||||
assert_eq!(krate.format_version, FORMAT_VERSION);
|
assert_eq!(krate.format_version, FORMAT_VERSION);
|
||||||
|
@ -101,7 +108,7 @@ fn main() -> Result<()> {
|
||||||
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
|
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bail!("Errors validating json {path}");
|
bail!("Errors validating json {}", path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -56,6 +56,9 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("bitmaps", "MPL-2.0+"),
|
("bitmaps", "MPL-2.0+"),
|
||||||
("bytesize", "Apache-2.0"),
|
("bytesize", "Apache-2.0"),
|
||||||
|
("ciborium", "Apache-2.0"),
|
||||||
|
("ciborium-io", "Apache-2.0"),
|
||||||
|
("ciborium-ll", "Apache-2.0"),
|
||||||
("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"),
|
("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"),
|
||||||
("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
|
("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
|
||||||
("im-rc", "MPL-2.0+"),
|
("im-rc", "MPL-2.0+"),
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
const ENTRY_LIMIT: usize = 900;
|
const ENTRY_LIMIT: usize = 900;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// FIXME: The following limits should be reduced eventually.
|
||||||
const ISSUES_ENTRY_LIMIT: usize = 1896;
|
const ISSUES_ENTRY_LIMIT: usize = 1894;
|
||||||
const ROOT_ENTRY_LIMIT: usize = 870;
|
const ROOT_ENTRY_LIMIT: usize = 870;
|
||||||
|
|
||||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
// revisions: llvm mir-opt3
|
||||||
// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
|
// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
// ignore-debug: the debug assertions get in the way
|
// ignore-debug: the debug assertions get in the way
|
||||||
|
// [mir-opt3]compile-flags: -Zmir-opt-level=3
|
||||||
|
// [mir-opt3]build-pass
|
||||||
|
|
||||||
|
// mir-opt3 is a regression test for https://github.com/rust-lang/rust/issues/98016
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(portable_simd)]
|
#![feature(portable_simd)]
|
||||||
|
@ -47,9 +52,8 @@ pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
// CHECK-LABEL: @wider_reduce_into_iter
|
// CHECK-LABEL: @wider_reduce_into_iter
|
||||||
pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 {
|
pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 {
|
||||||
// FIXME MIR inlining messes up LLVM optimizations.
|
// CHECK: zext <8 x i8>
|
||||||
// WOULD-CHECK: zext <8 x i8>
|
// CHECK-SAME: to <8 x i16>
|
||||||
// WOULD-CHECK-SAME: to <8 x i16>
|
// CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
|
||||||
// WOULD-CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
|
|
||||||
x.to_array().into_iter().map(u16::from).sum()
|
x.to_array().into_iter().map(u16::from).sum()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
// revisions: classic next
|
||||||
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
trait Foo: Fn(i32) -> i32 + Send {}
|
trait Foo: Fn(i32) -> i32 + Send {}
|
||||||
|
|
||||||
|
|
13
tests/ui/traits/new-solver/unsize-although-ambiguous.rs
Normal file
13
tests/ui/traits/new-solver/unsize-although-ambiguous.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
fn box_dyn_display(_: Box<dyn Display>) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// During coercion, we don't necessarily know whether `{integer}` implements
|
||||||
|
// `Display`. Before, that would cause us to bail out in the coercion loop when
|
||||||
|
// checking `{integer}: Unsize<dyn Display>`.
|
||||||
|
box_dyn_display(Box::new(1));
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
|
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
|
||||||
--> $DIR/issue-11515.rs:9:38
|
--> $DIR/issue-11515.rs:10:38
|
||||||
|
|
|
|
||||||
LL | let test = Box::new(Test { func: closure });
|
LL | let test = Box::new(Test { func: closure });
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
13
tests/ui/traits/trait-upcasting/issue-11515.next.stderr
Normal file
13
tests/ui/traits/trait-upcasting/issue-11515.next.stderr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/issue-11515.rs:10:38
|
||||||
|
|
|
||||||
|
LL | let test = Box::new(Test { func: closure });
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,9 +1,10 @@
|
||||||
|
// revisions: current next
|
||||||
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
struct Test {
|
struct Test {
|
||||||
func: Box<dyn FnMut() + 'static>,
|
func: Box<dyn FnMut() + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
|
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
|
||||||
let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
|
let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
|
Loading…
Add table
Add a link
Reference in a new issue