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 4 pull requests #118949

Merged
merged 8 commits into from
Dec 14, 2023
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/assert_module_sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ impl fmt::Display for CguReuse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
CguReuse::No => write!(f, "No"),
CguReuse::PreLto => write!(f, "PreLto "),
CguReuse::PostLto => write!(f, "PostLto "),
CguReuse::PreLto => write!(f, "PreLto"),
CguReuse::PostLto => write!(f, "PostLto"),
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,24 @@ where
if layout.abi.is_uninhabited() {
// `read_discriminant` should have excluded uninhabited variants... but ConstProp calls
// us on dead code.
// In the future we might want to allow this to permit code like this:
// (this is a Rust/MIR pseudocode mix)
// ```
// enum Option2 {
// Some(i32, !),
// None,
// }
//
// fn panic() -> ! { panic!() }
//
// let x: Option2;
// x.Some.0 = 42;
// x.Some.1 = panic();
// SetDiscriminant(x, Some);
// ```
// However, for now we don't generate such MIR, and this check here *has* found real
// bugs (see https://github.com/rust-lang/rust/issues/115145), so we will keep rejecting
// it.
throw_inval!(ConstPropNonsense)
}
// This cannot be `transmute` as variants *can* have a smaller size than the entire enum.
Expand Down
34 changes: 23 additions & 11 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,28 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
&mut self,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
) -> QueryResult<'tcx> {
match goal.predicate.term.unpack() {
ty::TermKind::Ty(term) => {
let alias = goal.predicate.projection_ty.to_ty(self.tcx());
self.eq(goal.param_env, alias, term)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
// FIXME(associated_const_equality): actually do something here.
ty::TermKind::Const(_) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
let tcx = self.tcx();
let projection_term = match goal.predicate.term.unpack() {
ty::TermKind::Ty(_) => goal.predicate.projection_ty.to_ty(tcx).into(),
ty::TermKind::Const(_) => ty::Const::new_unevaluated(
tcx,
ty::UnevaluatedConst::new(
goal.predicate.projection_ty.def_id,
goal.predicate.projection_ty.args,
),
tcx.type_of(goal.predicate.projection_ty.def_id)
.instantiate(tcx, goal.predicate.projection_ty.args),
)
.into(),
};
self.add_goal(goal.with(
tcx,
ty::PredicateKind::AliasRelate(
projection_term,
goal.predicate.term,
ty::AliasRelationDirection::Equate,
),
));
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
2 changes: 1 addition & 1 deletion src/librustdoc/html/render/search_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ pub(crate) fn build_index<'tcx>(

// Collect the index into a string
format!(
r#""{}":{}"#,
r#"["{}",{}]"#,
krate.name(tcx),
serde_json::to_string(&CrateData {
doc: crate_doc,
Expand Down
19 changes: 10 additions & 9 deletions src/librustdoc/html/render/write_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,23 +167,24 @@ pub(super) fn write_shared(
let mut krates = Vec::new();

if path.exists() {
let prefix = format!("\"{krate}\"");
let prefix = format!("[\"{krate}\"");
for line in BufReader::new(File::open(path)?).lines() {
let line = line?;
if !line.starts_with('"') {
if !line.starts_with("[\"") {
continue;
}
if line.starts_with(&prefix) {
continue;
}
if line.ends_with(",\\") {
if line.ends_with("],\\") {
ret.push(line[..line.len() - 2].to_string());
} else {
// Ends with "\\" (it's the case for the last added crate line)
ret.push(line[..line.len() - 1].to_string());
}
krates.push(
line.split('"')
line[1..] // We skip the `[` parent at the beginning of the line.
.split('"')
.find(|s| !s.is_empty())
.map(|s| s.to_owned())
.unwrap_or_else(String::new),
Expand Down Expand Up @@ -285,7 +286,7 @@ pub(super) fn write_shared(
let (mut all_sources, _krates) =
try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst);
all_sources.push(format!(
r#""{}":{}"#,
r#"["{}",{}]"#,
&krate.name(cx.tcx()),
hierarchy
.to_json_string()
Expand All @@ -296,9 +297,9 @@ pub(super) fn write_shared(
.replace("\\\"", "\\\\\"")
));
all_sources.sort();
let mut v = String::from("var srcIndex = JSON.parse('{\\\n");
let mut v = String::from("const srcIndex = new Map(JSON.parse('[\\\n");
v.push_str(&all_sources.join(",\\\n"));
v.push_str("\\\n}');\ncreateSrcSidebar();\n");
v.push_str("\\\n]'));\ncreateSrcSidebar();\n");
Ok(v.into_bytes())
};
write_invocation_specific("src-files.js", &make_sources)?;
Expand All @@ -316,11 +317,11 @@ pub(super) fn write_shared(
// with rustdoc running in parallel.
all_indexes.sort();
write_invocation_specific("search-index.js", &|| {
let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
let mut v = String::from("const searchIndex = new Map(JSON.parse('[\\\n");
v.push_str(&all_indexes.join(",\\\n"));
v.push_str(
r#"\
}');
]'));
if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
"#,
Expand Down
141 changes: 62 additions & 79 deletions src/librustdoc/html/static/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ const longItemTypes = [
const TY_GENERIC = itemTypes.indexOf("generic");
const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";

function hasOwnPropertyRustdoc(obj, property) {
return Object.prototype.hasOwnProperty.call(obj, property);
}

// In the search display, allows to switch between tabs.
function printTab(nb) {
let iter = 0;
Expand Down Expand Up @@ -1074,7 +1070,7 @@ function initSearch(rawSearchIndex) {

if (elem &&
elem.value !== "all crates" &&
hasOwnPropertyRustdoc(rawSearchIndex, elem.value)
rawSearchIndex.has(elem.value)
) {
return elem.value;
}
Expand Down Expand Up @@ -2524,11 +2520,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\
}

let crates = "";
const crates_list = Object.keys(rawSearchIndex);
if (crates_list.length > 1) {
if (rawSearchIndex.size > 1) {
crates = " in&nbsp;<div id=\"crate-search-div\"><select id=\"crate-search\">" +
"<option value=\"all crates\">all crates</option>";
for (const c of crates_list) {
for (const c of rawSearchIndex.keys()) {
crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
}
crates += "</select></div>";
Expand Down Expand Up @@ -2945,81 +2940,70 @@ ${item.displayPath}<span class="${type}">${name}</span>\
// Function type fingerprints are 128-bit bloom filters that are used to
// estimate the distance between function and query.
// This loop counts the number of items to allocate a fingerprint for.
for (const crate in rawSearchIndex) {
if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
continue;
}
for (const crate of rawSearchIndex.values()) {
// Each item gets an entry in the fingerprint array, and the crate
// does, too
id += rawSearchIndex[crate].t.length + 1;
id += crate.t.length + 1;
}
functionTypeFingerprint = new Uint32Array((id + 1) * 4);

// This loop actually generates the search item indexes, including
// normalized names, type signature objects and fingerprints, and aliases.
id = 0;
for (const crate in rawSearchIndex) {
if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
continue;
}

let crateSize = 0;

/**
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
* are arrays with the same length. `q`, `a`, and `c` use a sparse
* representation for compactness.
*
* `n[i]` contains the name of an item.
*
* `t[i]` contains the type of that item
* (as a string of characters that represent an offset in `itemTypes`).
*
* `d[i]` contains the description of that item.
*
* `q` contains the full paths of the items. For compactness, it is a set of
* (index, path) pairs used to create a map. If a given index `i` is
* not present, this indicates "same as the last index present".
*
* `i[i]` contains an item's parent, usually a module. For compactness,
* it is a set of indexes into the `p` array.
*
* `f[i]` contains function signatures, or `0` if the item isn't a function.
* Functions are themselves encoded as arrays. The first item is a list of
* types representing the function's inputs, and the second list item is a list
* of types representing the function's output. Tuples are flattened.
* Types are also represented as arrays; the first item is an index into the `p`
* array, while the second is a list of types representing any generic parameters.
*
* b[i] contains an item's impl disambiguator. This is only present if an item
* is defined in an impl block and, the impl block's type has more than one associated
* item with the same name.
*
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
* points into the n/t/d/q/i/f arrays.
*
* `doc` contains the description of the crate.
*
* `p` is a list of path/type pairs. It is used for parents and function parameters.
*
* `c` is an array of item indices that are deprecated.
*
* @type {{
* doc: string,
* a: Object,
* n: Array<string>,
* t: String,
* d: Array<string>,
* q: Array<[Number, string]>,
* i: Array<Number>,
* f: Array<RawFunctionSearchType>,
* p: Array<Object>,
* b: Array<[Number, String]>,
* c: Array<Number>
* }}
*/
const crateCorpus = rawSearchIndex[crate];

/**
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
* are arrays with the same length. `q`, `a`, and `c` use a sparse
* representation for compactness.
*
* `n[i]` contains the name of an item.
*
* `t[i]` contains the type of that item
* (as a string of characters that represent an offset in `itemTypes`).
*
* `d[i]` contains the description of that item.
*
* `q` contains the full paths of the items. For compactness, it is a set of
* (index, path) pairs used to create a map. If a given index `i` is
* not present, this indicates "same as the last index present".
*
* `i[i]` contains an item's parent, usually a module. For compactness,
* it is a set of indexes into the `p` array.
*
* `f[i]` contains function signatures, or `0` if the item isn't a function.
* Functions are themselves encoded as arrays. The first item is a list of
* types representing the function's inputs, and the second list item is a list
* of types representing the function's output. Tuples are flattened.
* Types are also represented as arrays; the first item is an index into the `p`
* array, while the second is a list of types representing any generic parameters.
*
* b[i] contains an item's impl disambiguator. This is only present if an item
* is defined in an impl block and, the impl block's type has more than one associated
* item with the same name.
*
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
* points into the n/t/d/q/i/f arrays.
*
* `doc` contains the description of the crate.
*
* `p` is a list of path/type pairs. It is used for parents and function parameters.
*
* `c` is an array of item indices that are deprecated.
*
* @type {{
* doc: string,
* a: Object,
* n: Array<string>,
* t: String,
* d: Array<string>,
* q: Array<[Number, string]>,
* i: Array<Number>,
* f: Array<RawFunctionSearchType>,
* p: Array<Object>,
* b: Array<[Number, String]>,
* c: Array<Number>
* }}
*/
for (const [crate, crateCorpus] of rawSearchIndex) {
searchWords.push(crate);
// This object should have exactly the same set of fields as the "row"
// object defined below. Your JavaScript runtime will thank you.
Expand Down Expand Up @@ -3145,14 +3129,13 @@ ${item.displayPath}<span class="${type}">${name}</span>\
id += 1;
searchIndex.push(row);
lastPath = row.path;
crateSize += 1;
}

if (aliases) {
const currentCrateAliases = new Map();
ALIASES.set(crate, currentCrateAliases);
for (const alias_name in aliases) {
if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
continue;
}

Expand All @@ -3168,7 +3151,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
}
}
}
currentIndex += crateSize;
currentIndex += itemTypes.length;
}
return searchWords;
}
Expand Down Expand Up @@ -3377,7 +3360,7 @@ if (typeof window !== "undefined") {
} else {
// Running in Node, not a browser. Run initSearch just to produce the
// exports.
initSearch({});
initSearch(new Map());
}


Expand Down
8 changes: 4 additions & 4 deletions src/librustdoc/html/static/js/src-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ function createSrcSidebar() {
title.className = "title";
title.innerText = "Files";
sidebar.appendChild(title);
Object.keys(srcIndex).forEach(key => {
srcIndex[key][NAME_OFFSET] = key;
hasFoundFile = createDirEntry(srcIndex[key], sidebar, "", hasFoundFile);
});
for (const [key, source] of srcIndex) {
source[NAME_OFFSET] = key;
hasFoundFile = createDirEntry(source, sidebar, "", hasFoundFile);
}

container.appendChild(sidebar);
// Focus on the current file in the source files sidebar.
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/traits/next-solver/closure-signature-inference-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// compile-flags: -Znext-solver
// check-pass

fn map<T: Default, U, F: FnOnce(T) -> U>(f: F) {
f(T::default());
}

fn main() {
map::<i32, _ /* ?U */, _ /* ?F */>(|x| x.to_string());
// PREVIOUSLY when confirming the `map` call, we register:
//
// (1.) ?F: FnOnce<(i32,)>
// (2.) <?F as FnOnce<(i32,)>>::Output projects-to ?U
//
// While (1.) is ambiguous, (2.) immediately gets processed
// and we infer `?U := <?F as FnOnce<(i32,)>>::Output`.
//
// Thus, the only pending obligation that remains is (1.).
// Since it is a trait obligation, we don't use it to deduce
// the closure signature, and we fail!
}
Loading
Loading