Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #113646

Merged
merged 17 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
if traits.contains(&trait_pred.def_id()) =>
{
let trait_pred = self.resolve_vars_if_possible(trait_pred);
if unsize_did == trait_pred.def_id() {
let self_ty = trait_pred.self_ty();
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
Expand All @@ -662,7 +663,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// Uncertain or unimplemented.
Ok(None) => {
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 unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ LLVMRustOptimize(
assert(!PGOUsePath && !PGOSampleUsePath);
PGOOpt = PGOOptions(PGOGenPath, "", "",
#if LLVM_VERSION_GE(17, 0)
"",
FS,
#endif
PGOOptions::IRInstr, PGOOptions::NoCSAction,
Expand All @@ -675,20 +676,23 @@ LLVMRustOptimize(
assert(!PGOSampleUsePath);
PGOOpt = PGOOptions(PGOUsePath, "", "",
#if LLVM_VERSION_GE(17, 0)
"",
FS,
#endif
PGOOptions::IRUse, PGOOptions::NoCSAction,
DebugInfoForProfiling);
} else if (PGOSampleUsePath) {
PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
#if LLVM_VERSION_GE(17, 0)
"",
FS,
#endif
PGOOptions::SampleUse, PGOOptions::NoCSAction,
DebugInfoForProfiling);
} else if (DebugInfoForProfiling) {
PGOOpt = PGOOptions("", "", "",
#if LLVM_VERSION_GE(17, 0)
"",
FS,
#endif
PGOOptions::NoAction, PGOOptions::NoCSAction,
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,21 +103,23 @@ impl<'tcx> Tables<'tcx> {
ty::Ref(_, _, _) => todo!(),
ty::FnDef(_, _) => todo!(),
ty::FnPtr(_) => todo!(),
ty::Placeholder(..) => todo!(),
ty::Dynamic(_, _, _) => todo!(),
ty::Closure(_, _) => todo!(),
ty::Generator(_, _, _) => todo!(),
ty::GeneratorWitness(_) => todo!(),
ty::GeneratorWitnessMIR(_, _) => todo!(),
ty::Never => todo!(),
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
fields.iter().map(|ty| self.intern_ty(ty)).collect(),
)),
ty::Alias(_, _) => todo!(),
ty::Param(_) => todo!(),
ty::Bound(_, _) => todo!(),
ty::Infer(_) => todo!(),
ty::Error(_) => todo!(),
ty::Placeholder(..)
| ty::GeneratorWitness(_)
| ty::GeneratorWitnessMIR(_, _)
| ty::Infer(_)
| ty::Error(_) => {
unreachable!();
}
}
}

Expand Down
145 changes: 144 additions & 1 deletion compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::ops::ControlFlow;

use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::util::supertraits;
Expand All @@ -11,7 +12,7 @@ use rustc_middle::traits::{
ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
ObligationCause, SelectionError,
};
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::DUMMY_SP;

use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource};
Expand Down Expand Up @@ -113,6 +114,12 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
),
) => 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
// `Certainty::Yes`, then they should've all been verified and don't
// need re-checking.
Expand Down Expand Up @@ -232,6 +239,9 @@ fn rematch_object<'tcx>(
{
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() {
// 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))
} else {
bug!()
Expand Down Expand Up @@ -305,3 +315,136 @@ fn rematch_object<'tcx>(
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)))
}
2 changes: 1 addition & 1 deletion src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def default_build_triple(verbose):
if uname is None:
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,
# at least for the subset of platforms we're willing to target.
Expand Down
21 changes: 9 additions & 12 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,16 +541,15 @@ impl TestProps {
}

fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
let check_no_run = |s| {
if config.mode != Mode::Ui && config.mode != Mode::Incremental {
panic!("`{}` header is only supported in UI and incremental tests", s);
}
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);
let check_no_run = |s| match (config.mode, s) {
(Mode::Ui, _) => (),
(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")
}
}
(mode, _) => panic!("`{s}` header is not supported in `{mode}` tests"),
};
let pass_mode = if config.parse_name_directive(ln, "check-pass") {
check_no_run("check-pass");
Expand All @@ -559,9 +558,7 @@ impl TestProps {
check_no_run("build-pass");
Some(PassMode::Build)
} else if config.parse_name_directive(ln, "run-pass") {
if config.mode != Mode::Ui {
panic!("`run-pass` header is only supported in UI tests")
}
check_no_run("run-pass");
Some(PassMode::Run)
} else {
None
Expand Down
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2752,6 +2752,10 @@ impl<'test> TestCx<'test> {
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 proc_res = self.verify_with_filecheck(&output_path);
if !proc_res.status.success() {
Expand Down
6 changes: 4 additions & 2 deletions src/tools/jsondocck/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ impl Cache {
/// Create a new cache, used to read files only once and otherwise store their contents.
pub fn new(config: &Config) -> Cache {
let root = Path::new(&config.doc_dir);
let filename = Path::new(&config.template).file_stem().unwrap();
let file_path = root.join(&Path::with_extension(Path::new(filename), "json"));
// `filename` needs to replace `-` with `_` to be sure the JSON path will always be valid.
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");

Cache {
Expand Down
11 changes: 9 additions & 2 deletions src/tools/jsondoclint/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};

use anyhow::{bail, Result};
use clap::Parser;
Expand All @@ -25,7 +26,7 @@ enum ErrorKind {

#[derive(Debug, Serialize)]
struct JsonOutput {
path: String,
path: PathBuf,
errors: Vec<Error>,
}

Expand All @@ -45,6 +46,12 @@ struct Cli {
fn main() -> Result<()> {
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 krate: Crate = serde_json::from_str(&contents)?;
assert_eq!(krate.format_version, FORMAT_VERSION);
Expand Down Expand Up @@ -101,7 +108,7 @@ fn main() -> Result<()> {
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
}
}
bail!("Errors validating json {path}");
bail!("Errors validating json {}", path.display());
}

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
// tidy-alphabetical-start
("bitmaps", "MPL-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"),
("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
("im-rc", "MPL-2.0+"),
Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};

const ENTRY_LIMIT: usize = 900;
// 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 EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
Expand Down
Loading
Loading