Skip to content

Rollup of 7 pull requests #102990

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

Closed
wants to merge 16 commits into from
Closed
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_target::abi::Size;

impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
#[instrument(level = "trace", skip(self, bx))]
@@ -285,6 +286,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("Only valid to do a DynStar cast into a DynStar type")
};
let vtable = get_vtable(bx.cx(), source.ty(self.mir, bx.tcx()), trait_ref);
let vtable = bx.pointercast(vtable, bx.cx().type_ptr_to(bx.cx().type_isize()));
// FIXME(dyn-star): this is probably not the best way to check if this is
// a pointer, and really we should ensure that the value is a suitable
// pointer earlier in the compilation process.
let data = match operand.layout.pointee_info_at(bx.cx(), Size::ZERO) {
Some(_) => bx.ptrtoint(data, bx.cx().type_isize()),
None => data,
};
OperandValue::Pair(data, vtable)
}
mir::CastKind::Pointer(
14 changes: 9 additions & 5 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
@@ -1739,11 +1739,15 @@ impl TargetOptions {
self.lld_flavor_json,
self.linker_is_gnu_json,
);
match linker_flavor {
LinkerFlavor::Gnu(_, Lld::Yes)
| LinkerFlavor::Darwin(_, Lld::Yes)
| LinkerFlavor::Msvc(Lld::Yes) => {}
_ => add_link_args_iter(args, linker_flavor, args_json.iter().cloned()),
// Normalize to no lld to avoid asserts.
let linker_flavor = match linker_flavor {
LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
_ => linker_flavor,
};
if !args.contains_key(&linker_flavor) {
add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
}
}
}
6 changes: 2 additions & 4 deletions src/bootstrap/check.rs
Original file line number Diff line number Diff line change
@@ -451,14 +451,12 @@ macro_rules! tool_check_step {
}

tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree);
// Clippy and Rustfmt are hybrids. They are external tools, but use a git subtree instead
// Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead
// of a submodule. Since the SourceType only drives the deny-warnings
// behavior, treat it as in-tree so that any new warnings in clippy will be
// rejected.
tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
// Miri on the other hand is treated as out of tree, since InTree also causes it to
// be run as part of `check`, which can fail on platforms which libffi-sys has no support for.
tool_check_step!(Miri, "src/tools/miri", SourceType::Submodule);
tool_check_step!(Miri, "src/tools/miri", SourceType::InTree);
tool_check_step!(Rls, "src/tools/rls", SourceType::InTree);
tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);

35 changes: 6 additions & 29 deletions src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
@@ -735,7 +735,7 @@ impl Step for Rustc {
}

macro_rules! tool_doc {
($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], in_tree = $in_tree:expr $(,)?) => {
($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $tool {
target: TargetSelection,
@@ -791,12 +791,6 @@ macro_rules! tool_doc {
t!(fs::create_dir_all(&out_dir));
t!(symlink_dir_force(&builder.config, &out, &out_dir));

let source_type = if $in_tree == true {
SourceType::InTree
} else {
SourceType::Submodule
};

// Build cargo command.
let mut cargo = prepare_tool_cargo(
builder,
@@ -805,7 +799,7 @@ macro_rules! tool_doc {
target,
"doc",
$path,
source_type,
SourceType::InTree,
&[],
);

@@ -821,38 +815,21 @@ macro_rules! tool_doc {
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("--generate-link-to-definition");
cargo.rustdocflag("-Zunstable-options");
if $in_tree == true {
builder.run(&mut cargo.into());
} else {
// Allow out-of-tree docs to fail (since the tool might be in a broken state).
if !builder.try_run(&mut cargo.into()) {
builder.info(&format!(
"WARNING: tool {} failed to document; ignoring failure because it is an out-of-tree tool",
stringify!($tool).to_lowercase(),
));
}
}
builder.run(&mut cargo.into());
}
}
}
}

tool_doc!(
Rustdoc,
"rustdoc-tool",
"src/tools/rustdoc",
["rustdoc", "rustdoc-json-types"],
in_tree = true
);
tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"],);
tool_doc!(
Rustfmt,
"rustfmt-nightly",
"src/tools/rustfmt",
["rustfmt-nightly", "rustfmt-config_proc_macro"],
in_tree = true
);
tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"], in_tree = true);
tool_doc!(Miri, "miri", "src/tools/miri", ["miri"], in_tree = false);
tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
tool_doc!(Miri, "miri", "src/tools/miri", ["miri"]);

#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
4 changes: 2 additions & 2 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
@@ -503,7 +503,7 @@ impl Step for Miri {
host,
"run",
"src/tools/miri/cargo-miri",
SourceType::Submodule,
SourceType::InTree,
&[],
);
cargo.add_rustc_lib_path(builder, compiler);
@@ -550,7 +550,7 @@ impl Step for Miri {
host,
"test",
"src/tools/miri",
SourceType::Submodule,
SourceType::InTree,
&[],
);
cargo.add_rustc_lib_path(builder, compiler);
23 changes: 9 additions & 14 deletions src/bootstrap/tool.rs
Original file line number Diff line number Diff line change
@@ -795,7 +795,6 @@ macro_rules! tool_extended {
$path:expr,
$tool_name:expr,
stable = $stable:expr,
$(in_tree = $in_tree:expr,)?
$(tool_std = $tool_std:literal,)?
$extra_deps:block;)+) => {
$(
@@ -848,11 +847,7 @@ macro_rules! tool_extended {
path: $path,
extra_features: $sel.extra_features,
is_optional_tool: true,
source_type: if false $(|| $in_tree)* {
SourceType::InTree
} else {
SourceType::Submodule
},
source_type: SourceType::InTree,
})
}
}
@@ -865,17 +860,17 @@ macro_rules! tool_extended {
// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
// invoke Cargo to build bootstrap. See the comment there for more details.
tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true, in_tree=true, {};
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true, in_tree=true, {};
Clippy, "src/tools/clippy", "clippy-driver", stable=true, in_tree=true, {};
Miri, "src/tools/miri", "miri", stable=false, in_tree=true, {};
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, in_tree=true, {};
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true, {};
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true, {};
Clippy, "src/tools/clippy", "clippy-driver", stable=true, {};
Miri, "src/tools/miri", "miri", stable=false, {};
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, {};
// FIXME: tool_std is not quite right, we shouldn't allow nightly features.
// But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0,
// and this is close enough for now.
Rls, "src/tools/rls", "rls", stable=true, in_tree=true, tool_std=true, {};
RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, tool_std=true, {};
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {};
Rls, "src/tools/rls", "rls", stable=true, tool_std=true, {};
RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true, {};
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {};
);

impl<'a> Builder<'a> {
2 changes: 1 addition & 1 deletion src/ci/scripts/should-skip-this.sh
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then
# those files are present in the diff a submodule was updated.
echo "Submodules were updated"
elif ! (git diff --quiet "$BASE_COMMIT" -- \
src/tools/clippy src/tools/rustfmt src/tools/miri
src/tools/clippy src/tools/rustfmt src/tools/miri \
library/std/src/sys); then
# There is not an easy blanket search for subtrees. For now, manually list
# the subtrees.
9 changes: 3 additions & 6 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -692,16 +692,13 @@ pre, .rustdoc.source .example-wrap {

.item-info {
display: block;
margin-left: 24px;
}

.content .item-info code {
.item-info code {
font-size: 0.875rem;
}

.content .item-info {
margin-left: 24px;
}

#main-content > .item-info {
margin-top: 0;
margin-left: 0;
@@ -1945,7 +1942,7 @@ in storage.js plus the media query with (min-width: 701px)
}

/* Align summary-nested and unnested item-info gizmos. */
.content .impl-items > .item-info {
.impl-items > .item-info {
margin-left: 34px;
}
}
17 changes: 17 additions & 0 deletions src/test/ui/dyn-star/box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// run-pass
// compile-flags: -C opt-level=0

#![feature(dyn_star)]
#![allow(incomplete_features)]

use std::fmt::Display;

fn make_dyn_star() -> dyn* Display {
Box::new(42) as dyn* Display
}

fn main() {
let x = make_dyn_star();

println!("{x}");
}
10 changes: 10 additions & 0 deletions src/test/ui/issues/issue-102964.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use std::rc::Rc;
type Foo<'a, T> = &'a dyn Fn(&T);
type RcFoo<'a, T> = Rc<Foo<'a, T>>;

fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
//~^ ERROR mismatched types
let rc = Rc::new(function);
}

fn main() {}
19 changes: 19 additions & 0 deletions src/test/ui/issues/issue-102964.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0308]: mismatched types
--> $DIR/issue-102964.rs:5:41
|
LL | fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
| ------------ ^^^^^^^^ expected struct `Rc`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
= note: expected struct `Rc<&dyn for<'a> Fn(&'a T)>`
found unit type `()`
help: consider returning the local binding `rc`
|
LL ~ let rc = Rc::new(function);
LL + rc
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
263 changes: 137 additions & 126 deletions src/tools/tidy/src/features.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
//! * Language features in a group are sorted by feature name.
use crate::walk::{filter_dirs, walk, walk_many};
use std::collections::HashMap;
use std::collections::hash_map::{Entry, HashMap};
use std::fmt;
use std::fs;
use std::num::NonZeroU32;
@@ -280,13 +280,14 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
}

pub fn collect_lang_features(base_compiler_path: &Path, bad: &mut bool) -> Features {
let mut all = collect_lang_features_in(base_compiler_path, "active.rs", bad);
all.extend(collect_lang_features_in(base_compiler_path, "accepted.rs", bad));
all.extend(collect_lang_features_in(base_compiler_path, "removed.rs", bad));
all
let mut features = Features::new();
collect_lang_features_in(&mut features, base_compiler_path, "active.rs", bad);
collect_lang_features_in(&mut features, base_compiler_path, "accepted.rs", bad);
collect_lang_features_in(&mut features, base_compiler_path, "removed.rs", bad);
features
}

fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features {
fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, bad: &mut bool) {
let path = base.join("rustc_feature").join("src").join(file);
let contents = t!(fs::read_to_string(&path));

@@ -298,135 +299,145 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
let mut in_feature_group = false;
let mut prev_names = vec![];

contents
.lines()
.zip(1..)
.filter_map(|(line, line_number)| {
let line = line.trim();

// Within -start and -end, the tracking issue can be omitted.
match line {
"// no-tracking-issue-start" => {
next_feature_omits_tracking_issue = true;
return None;
}
"// no-tracking-issue-end" => {
next_feature_omits_tracking_issue = false;
return None;
}
_ => {}
let lines = contents.lines().zip(1..);
for (line, line_number) in lines {
let line = line.trim();

// Within -start and -end, the tracking issue can be omitted.
match line {
"// no-tracking-issue-start" => {
next_feature_omits_tracking_issue = true;
continue;
}
"// no-tracking-issue-end" => {
next_feature_omits_tracking_issue = false;
continue;
}
_ => {}
}

if line.starts_with(FEATURE_GROUP_START_PREFIX) {
if in_feature_group {
tidy_error!(
bad,
"{}:{}: \
if line.starts_with(FEATURE_GROUP_START_PREFIX) {
if in_feature_group {
tidy_error!(
bad,
"{}:{}: \
new feature group is started without ending the previous one",
path.display(),
line_number,
);
}

in_feature_group = true;
prev_names = vec![];
return None;
} else if line.starts_with(FEATURE_GROUP_END_PREFIX) {
in_feature_group = false;
prev_names = vec![];
return None;
path.display(),
line_number,
);
}

let mut parts = line.split(',');
let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
Some("active") => Status::Unstable,
Some("incomplete") => Status::Unstable,
Some("removed") => Status::Removed,
Some("accepted") => Status::Stable,
_ => return None,
};
let name = parts.next().unwrap().trim();

let since_str = parts.next().unwrap().trim().trim_matches('"');
let since = match since_str.parse() {
Ok(since) => Some(since),
Err(err) => {
tidy_error!(
bad,
"{}:{}: failed to parse since: {} ({:?})",
path.display(),
line_number,
since_str,
err,
);
None
}
};
if in_feature_group {
if prev_names.last() > Some(&name) {
// This assumes the user adds the feature name at the end of the list, as we're
// not looking ahead.
let correct_index = match prev_names.binary_search(&name) {
Ok(_) => {
// This only occurs when the feature name has already been declared.
tidy_error!(
bad,
"{}:{}: duplicate feature {}",
path.display(),
line_number,
name,
);
// skip any additional checks for this line
return None;
}
Err(index) => index,
};
in_feature_group = true;
prev_names = vec![];
continue;
} else if line.starts_with(FEATURE_GROUP_END_PREFIX) {
in_feature_group = false;
prev_names = vec![];
continue;
}

let correct_placement = if correct_index == 0 {
"at the beginning of the feature group".to_owned()
} else if correct_index == prev_names.len() {
// I don't believe this is reachable given the above assumption, but it
// doesn't hurt to be safe.
"at the end of the feature group".to_owned()
} else {
format!(
"between {} and {}",
prev_names[correct_index - 1],
prev_names[correct_index],
)
};
let mut parts = line.split(',');
let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
Some("active") => Status::Unstable,
Some("incomplete") => Status::Unstable,
Some("removed") => Status::Removed,
Some("accepted") => Status::Stable,
_ => continue,
};
let name = parts.next().unwrap().trim();

let since_str = parts.next().unwrap().trim().trim_matches('"');
let since = match since_str.parse() {
Ok(since) => Some(since),
Err(err) => {
tidy_error!(
bad,
"{}:{}: failed to parse since: {} ({:?})",
path.display(),
line_number,
since_str,
err,
);
None
}
};
if in_feature_group {
if prev_names.last() > Some(&name) {
// This assumes the user adds the feature name at the end of the list, as we're
// not looking ahead.
let correct_index = match prev_names.binary_search(&name) {
Ok(_) => {
// This only occurs when the feature name has already been declared.
tidy_error!(
bad,
"{}:{}: duplicate feature {}",
path.display(),
line_number,
name,
);
// skip any additional checks for this line
continue;
}
Err(index) => index,
};

tidy_error!(
bad,
"{}:{}: feature {} is not sorted by feature name (should be {})",
path.display(),
line_number,
name,
correct_placement,
);
}
prev_names.push(name);
let correct_placement = if correct_index == 0 {
"at the beginning of the feature group".to_owned()
} else if correct_index == prev_names.len() {
// I don't believe this is reachable given the above assumption, but it
// doesn't hurt to be safe.
"at the end of the feature group".to_owned()
} else {
format!(
"between {} and {}",
prev_names[correct_index - 1],
prev_names[correct_index],
)
};

tidy_error!(
bad,
"{}:{}: feature {} is not sorted by feature name (should be {})",
path.display(),
line_number,
name,
correct_placement,
);
}
prev_names.push(name);
}

let issue_str = parts.next().unwrap().trim();
let tracking_issue = if issue_str.starts_with("None") {
if level == Status::Unstable && !next_feature_omits_tracking_issue {
tidy_error!(
bad,
"{}:{}: no tracking issue for feature {}",
path.display(),
line_number,
name,
);
}
None
} else {
let s = issue_str.split('(').nth(1).unwrap().split(')').next().unwrap();
Some(s.parse().unwrap())
};
Some((name.to_owned(), Feature { level, since, has_gate_test: false, tracking_issue }))
})
.collect()
let issue_str = parts.next().unwrap().trim();
let tracking_issue = if issue_str.starts_with("None") {
if level == Status::Unstable && !next_feature_omits_tracking_issue {
tidy_error!(
bad,
"{}:{}: no tracking issue for feature {}",
path.display(),
line_number,
name,
);
}
None
} else {
let s = issue_str.split('(').nth(1).unwrap().split(')').next().unwrap();
Some(s.parse().unwrap())
};
match features.entry(name.to_owned()) {
Entry::Occupied(e) => {
tidy_error!(
bad,
"{}:{} feature {name} already specified with status '{}'",
path.display(),
line_number,
e.get().level,
);
}
Entry::Vacant(e) => {
e.insert(Feature { level, since, has_gate_test: false, tracking_issue });
}
}
}
}

fn get_and_check_lib_features(