Auto merge of #108789 - matthiaskrgr:rollup-nyurto8, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #108244 (Add test for semicolon recovery ICE)
 - #108746 (Don't project to RPITIT that has no default value)
 - #108764 (Tweaks to -Zdrop-tracking-mir)
 - #108770 (Improve documentation and argument naming of some TyCtxt methods)
 - #108773 (x fmt: Only check modified files locally)
 - #108775 (Use the correct bound vars in return type suggestion.)
 - #108776 (Make `x test tidy` less noisy)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-06 00:43:06 +00:00
commit 8c0f83d773
17 changed files with 150 additions and 53 deletions

View File

@ -1510,6 +1510,14 @@ fn opaque_type_cycle_error(
{
label_match(interior_ty.ty, interior_ty.span);
}
if tcx.sess.opts.unstable_opts.drop_tracking_mir
&& let DefKind::Generator = tcx.def_kind(closure_def_id)
{
let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
for interior_ty in &generator_layout.field_tys {
label_match(interior_ty.ty, interior_ty.source_info.span);
}
}
}
}
}

View File

@ -344,8 +344,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
in_trait,
..
}) => {
if in_trait {
assert!(tcx.impl_defaultness(owner).has_value());
if in_trait && !tcx.impl_defaultness(owner).has_value() {
span_bug!(tcx.def_span(def_id), "tried to get type of this RPITIT with no definition");
}
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
}

View File

@ -669,6 +669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// This routine checks if the return type is left as default, the method is not part of an
/// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
/// type.
#[instrument(level = "trace", skip(self, err))]
pub(in super::super) fn suggest_missing_return_type(
&self,
err: &mut Diagnostic,
@ -705,28 +706,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return true
}
}
hir::FnRetTy::Return(ty) => {
let span = ty.span;
hir::FnRetTy::Return(hir_ty) => {
let span = hir_ty.span;
if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty),
..
}) = self.tcx.hir().get(item_id.hir_id())
&& let hir::OpaqueTy {
bounds: [bound], ..
} = op_ty
&& let hir::GenericBound::LangItemTrait(
hir::LangItem::Future, _, _, generic_args) = bound
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
&& let hir::TypeBinding { kind, .. } = ty_binding
&& let hir::TypeBindingKind::Equality { term } = kind
&& let hir::Term::Ty(term_ty) = term {
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty),
..
}) = self.tcx.hir().get(item_id.hir_id())
&& let [hir::GenericBound::LangItemTrait(
hir::LangItem::Future, _, _, generic_args)] = op_ty.bounds
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } = ty_binding.kind
{
// Check if async function's return type was omitted.
// Don't emit suggestions if the found type is `impl Future<...>`.
debug!("suggest_missing_return_type: found = {:?}", found);
debug!(?found);
if found.is_suggestable(self.tcx, false) {
if term_ty.span.is_empty() {
if term.span.is_empty() {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else {
@ -737,11 +734,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
let ty = self.astconv().ast_ty_to_ty(ty);
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
debug!("return type {:?}", hir_ty);
let ty = self.astconv().ast_ty_to_ty(hir_ty);
debug!("return type {:?}", ty);
debug!("expected type {:?}", expected);
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize(span, ty);
let ty = self.tcx.erase_late_bound_regions(ty);

View File

@ -100,8 +100,9 @@ impl<'tcx> TraitDef {
}
impl<'tcx> TyCtxt<'tcx> {
pub fn for_each_impl<F: FnMut(DefId)>(self, def_id: DefId, mut f: F) {
let impls = self.trait_impls_of(def_id);
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
@ -114,26 +115,28 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
/// Iterate over every impl that could possibly match the
/// self type `self_ty`.
/// Iterate over every impl that could possibly match the self type `self_ty`.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn for_each_relevant_impl<F: FnMut(DefId)>(
self,
def_id: DefId,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
mut f: F,
) {
let _: Option<()> = self.find_map_relevant_impl(def_id, self_ty, |did| {
let _: Option<()> = self.find_map_relevant_impl(trait_def_id, self_ty, |did| {
f(did);
None
});
}
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn non_blanket_impls_for_ty(
self,
def_id: DefId,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
) -> impl Iterator<Item = DefId> + 'tcx {
let impls = self.trait_impls_of(def_id);
let impls = self.trait_impls_of(trait_def_id);
if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsInfer) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
return impls.iter().copied();
@ -145,9 +148,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
/// the first non-none value.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(
self,
def_id: DefId,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
mut f: F,
) -> Option<T> {
@ -156,7 +161,7 @@ impl<'tcx> TyCtxt<'tcx> {
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
let impls = self.trait_impls_of(def_id);
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
if let result @ Some(_) = f(impl_def_id) {
@ -190,9 +195,11 @@ impl<'tcx> TyCtxt<'tcx> {
None
}
/// Returns an iterator containing all impls
pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);
/// Returns an iterator containing all impls for `trait_def_id`.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn all_impls(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(trait_def_id);
blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned()
}

View File

@ -1872,12 +1872,14 @@ fn check_must_not_suspend_def(
data: SuspendCheckData<'_>,
) -> bool {
if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) {
let msg = format!(
"{}`{}`{} held across a suspend point, but should not be",
data.descr_pre,
tcx.def_path_str(def_id),
data.descr_post,
);
let msg = rustc_errors::DelayDm(|| {
format!(
"{}`{}`{} held across a suspend point, but should not be",
data.descr_pre,
tcx.def_path_str(def_id),
data.descr_post,
)
});
tcx.struct_span_lint_hir(
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
hir_id,

View File

@ -149,6 +149,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
&mut self,
_: &InferCtxt<'tcx>,
) -> Vec<PredicateObligation<'tcx>> {
unimplemented!()
std::mem::take(&mut self.obligations)
}
}

View File

@ -2199,7 +2199,8 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
Err(guar) => return Progress::error(tcx, guar),
};
// We don't support specialization for RPITITs anyways... yet.
if !leaf_def.is_final() {
// Also don't try to project to an RPITIT that has no value
if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
return Progress { term: tcx.ty_error_misc().into(), obligations };
}

View File

@ -2,6 +2,7 @@
use crate::builder::Builder;
use crate::util::{output, program_out_of_date, t};
use build_helper::ci::CiEnv;
use build_helper::git::get_git_modified_files;
use ignore::WalkBuilder;
use std::collections::VecDeque;
@ -144,8 +145,10 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
let untracked_paths = untracked_paths_output
.lines()
.filter(|entry| entry.starts_with("??"))
.map(|entry| {
entry.split(' ').nth(1).expect("every git status entry should list a path")
.filter_map(|entry| {
let path =
entry.split(' ').nth(1).expect("every git status entry should list a path");
path.ends_with(".rs").then_some(path)
});
for untracked_path in untracked_paths {
println!("skip untracked path {} during rustfmt invocations", untracked_path);
@ -156,7 +159,10 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
// preventing the latter from being formatted.
ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
}
if !check && paths.is_empty() {
// Only check modified files locally to speed up runtime.
// We still check all files in CI to avoid bugs in `get_modified_rs_files` letting regressions slip through;
// we also care about CI time less since this is still very fast compared to building the compiler.
if !CiEnv::is_ci() && paths.is_empty() {
match get_modified_rs_files(build) {
Ok(Some(files)) => {
for file in files {

View File

@ -46,8 +46,10 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
// Stage 1: create list
let error_codes = extract_error_codes(root_path, &mut errors);
println!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
if verbose {
println!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
}
// Stage 2: check list has docs
let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose);

View File

@ -219,8 +219,6 @@ pub fn check(
for line in lines {
println!("* {line}");
}
} else {
println!("* {} features", features.len());
}
CollectedFeatures { lib: lib_features, lang: features }

View File

@ -0,0 +1,16 @@
#![feature(return_position_impl_trait_in_trait)]
//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
trait MyTrait {
fn foo(&self) -> impl Sized;
fn bar(&self) -> impl Sized;
}
impl MyTrait for i32 {
//~^ ERROR not all trait items implemented, missing: `foo`
fn bar(&self) -> impl Sized {
self.foo()
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dont-project-to-rpitit-with-no-value.rs:1:12
|
LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/dont-project-to-rpitit-with-no-value.rs:9:1
|
LL | fn foo(&self) -> impl Sized;
| ---------------------------- `foo` from trait
...
LL | impl MyTrait for i32 {
| ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0046`.

View File

@ -114,6 +114,9 @@ error[E0720]: cannot resolve opaque type
|
LL | fn generator_hold() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | let x = generator_hold();
| - generator captures itself here
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:90:26

View File

@ -0,0 +1,5 @@
fn foo() {}
fn main() {
foo(;
foo(;
} //~ ERROR mismatched closing delimiter

View File

@ -0,0 +1,13 @@
error: mismatched closing delimiter: `}`
--> $DIR/issue-108242-semicolon-recovery.rs:4:8
|
LL | fn main() {
| - closing delimiter possibly meant for this
LL | foo(;
LL | foo(;
| ^ unclosed delimiter
LL | }
| ^ mismatched closing delimiter
error: aborting due to previous error

View File

@ -0,0 +1,6 @@
// edition: 2021
async fn str<T>(T: &str) -> &str { &str }
//~^ ERROR mismatched types
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/issue-107860.rs:3:36
|
LL | async fn str<T>(T: &str) -> &str { &str }
| ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<...>}`
|
= note: expected reference `&str`
found reference `&for<'a> fn(&'a str) -> impl Future<Output = &'a str> {str::<_>}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.