mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
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:
commit
8c0f83d773
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -219,8 +219,6 @@ pub fn check(
|
||||
for line in lines {
|
||||
println!("* {line}");
|
||||
}
|
||||
} else {
|
||||
println!("* {} features", features.len());
|
||||
}
|
||||
|
||||
CollectedFeatures { lib: lib_features, lang: features }
|
||||
|
@ -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() {}
|
@ -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`.
|
@ -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
|
||||
|
@ -0,0 +1,5 @@
|
||||
fn foo() {}
|
||||
fn main() {
|
||||
foo(;
|
||||
foo(;
|
||||
} //~ ERROR mismatched closing delimiter
|
@ -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
|
||||
|
6
tests/ui/suggestions/issue-107860.rs
Normal file
6
tests/ui/suggestions/issue-107860.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// edition: 2021
|
||||
|
||||
async fn str<T>(T: &str) -> &str { &str }
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
fn main() {}
|
12
tests/ui/suggestions/issue-107860.stderr
Normal file
12
tests/ui/suggestions/issue-107860.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user