From 7634c5916a056c8a448101a309d9d9d61a6b3c26 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Mar 2023 18:36:02 +0000 Subject: [PATCH 1/9] Don't project to RPITIT that has no default value --- .../rustc_hir_analysis/src/collect/type_of.rs | 4 ++-- .../src/traits/project.rs | 3 ++- .../dont-project-to-rpitit-with-no-value.rs | 16 ++++++++++++++ ...ont-project-to-rpitit-with-no-value.stderr | 21 +++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs create mode 100644 tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 50073d94ea5c9..f779da1f7afa0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -344,8 +344,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> 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) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 870ecc2a9707a..2c00d7da80097 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2200,7 +2200,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 }; } diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs new file mode 100644 index 0000000000000..746a4a929aeb1 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs @@ -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() {} diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr new file mode 100644 index 0000000000000..d7f2e460fb0b9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr @@ -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 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`. From 0916616feca5d121cd1705daa7264c5d05276fac Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 28 Jan 2023 22:45:52 +0000 Subject: [PATCH 2/9] drop_tracking_mir: diagnose recursive generator. --- compiler/rustc_hir_analysis/src/check/check.rs | 8 ++++++++ ...sive-impl-trait-type-indirect.drop_tracking_mir.stderr | 3 +++ 2 files changed, 11 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 848828175e2d8..336c42622f517 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1511,6 +1511,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); + } + } } } } diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr index 662c74bcdc0d0..9c67f17e96358 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr @@ -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 From 135db79bc8f775982f401605e556a532c10252ed Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 28 Jan 2023 22:46:25 +0000 Subject: [PATCH 3/9] drop_tracking_mir: avoid good path bug. --- compiler/rustc_mir_transform/src/generator.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 2e97312ee5048..746326f9bde8c 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -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, From fba5d3dd03a0dcb0ed544950bd00f50f85f493ef Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 28 Jan 2023 22:46:46 +0000 Subject: [PATCH 4/9] drop_tracking_mir: support new solver. --- compiler/rustc_trait_selection/src/solve/fulfill.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index a55b984fd630d..38120b9760f3d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -149,6 +149,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { &mut self, _: &InferCtxt<'tcx>, ) -> Vec> { - unimplemented!() + std::mem::take(&mut self.obligations) } } From 1836fe44b51f5e3bd15a998de42641f5fa99cba1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Mar 2023 13:35:13 +0100 Subject: [PATCH 5/9] Improve documentation and argument naming of some TyCtxt methods --- compiler/rustc_middle/src/ty/trait_def.rs | 33 ++++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 233c0df2d3c77..649a58c917073 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -100,8 +100,9 @@ impl<'tcx> TraitDef { } impl<'tcx> TyCtxt<'tcx> { - pub fn for_each_impl(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(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( 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 + '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 Option>( self, - def_id: DefId, + trait_def_id: DefId, self_ty: Ty<'tcx>, mut f: F, ) -> Option { @@ -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 + '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 + '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() } From a435b3c0cde7d7b0b190c208bfa4e5a00960816b Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 19 Feb 2023 21:15:49 +0100 Subject: [PATCH 6/9] add test for https://github.com/rust-lang/rust/issues/108242 --- .../issues/issue-108242-semicolon-recovery.rs | 5 +++++ .../issues/issue-108242-semicolon-recovery.stderr | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/parser/issues/issue-108242-semicolon-recovery.rs create mode 100644 tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr diff --git a/tests/ui/parser/issues/issue-108242-semicolon-recovery.rs b/tests/ui/parser/issues/issue-108242-semicolon-recovery.rs new file mode 100644 index 0000000000000..2fc0b29477b8e --- /dev/null +++ b/tests/ui/parser/issues/issue-108242-semicolon-recovery.rs @@ -0,0 +1,5 @@ +fn foo() {} +fn main() { + foo(; + foo(; +} //~ ERROR mismatched closing delimiter diff --git a/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr b/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr new file mode 100644 index 0000000000000..f68d6d5010d6d --- /dev/null +++ b/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr @@ -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 + From 620efed932766b4cd516a26205fe47f51f54f911 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 08:16:32 -0600 Subject: [PATCH 7/9] x fmt: Only check modified files locally Previously, `x fmt` would only format modified files, while `x fmt .` and `x fmt --check` would still look at all files. After this change, `x fmt --check` only looks at modified files locally. I feel pretty confident in this change - other than https://github.com/rust-lang/rust/issues/106261, no one has reported bugs in `get_modified_rs_files` since it was added in https://github.com/rust-lang/rust/pull/105702. --- src/bootstrap/format.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6d5753e8a6d4d..3637251256283 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -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; @@ -156,7 +157,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 { From b4a5f4c22101110720d666bcf213dff84e58ee92 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Mar 2023 14:49:29 +0000 Subject: [PATCH 8/9] Make `x test tidy` less noisy Before: ``` Building tool tidy (stage0) Finished release [optimized + debuginfo] target(s) in 0.29s fmt check skip untracked path chrome_profiler.json during rustfmt invocations skip untracked path query_impl-default,args.mm_profdata during rustfmt invocations skip untracked path query_impl-llvm.txt during rustfmt invocations skip untracked path query_impl-mono_items.txt during rustfmt invocations skip untracked path query_impl-summarize.txt during rustfmt invocations skip untracked path rustc.svg during rustfmt invocations skip untracked path rustc_middle.mono_items.json during rustfmt invocations skip untracked path rustc_middle.mono_items.md during rustfmt invocations skip untracked path rustc_query_impl.mono_items-thread_local_attr.json during rustfmt invocations skip untracked path rustc_query_impl.mono_items-thread_local_macro.json during rustfmt invocations skip untracked path rustc_query_impl.mono_items.md during rustfmt invocations tidy check Found 505 error codes Highest error code: `E0793` * 397 features Ensuring the YAML anchors in the GitHub Actions config were expanded Building tool expand-yaml-anchors (stage0) Finished release [optimized + debuginfo] target(s) in 0.14s Build completed successfully in 0:00:54 ``` After: ``` Building tool tidy (stage0) Finished release [optimized + debuginfo] target(s) in 2.24s fmt check tidy check Ensuring the YAML anchors in the GitHub Actions config were expanded Building tool expand-yaml-anchors (stage0) Finished release [optimized + debuginfo] target(s) in 0.14s Build completed successfully in 0:00:04 ``` --- src/bootstrap/format.rs | 6 ++++-- src/tools/tidy/src/error_codes.rs | 6 ++++-- src/tools/tidy/src/features.rs | 2 -- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6d5753e8a6d4d..f7b5fc5656a72 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -144,8 +144,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); diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index c60caa0d49c6a..5dac780ced4cd 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -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); diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index af92e6eb86376..80dd5886f0867 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -219,8 +219,6 @@ pub fn check( for line in lines { println!("* {line}"); } - } else { - println!("* {} features", features.len()); } CollectedFeatures { lib: lib_features, lang: features } From 1e9b58bdf8dcb88ee21fbb8b0d2e86cba2b4cbb6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Mar 2023 14:49:33 +0000 Subject: [PATCH 9/9] Use the correct bound vars in return type suggestion. --- .../src/fn_ctxt/suggestions.rs | 45 +++++++++---------- tests/ui/suggestions/issue-107860.rs | 6 +++ tests/ui/suggestions/issue-107860.stderr | 12 +++++ 3 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 tests/ui/suggestions/issue-107860.rs create mode 100644 tests/ui/suggestions/issue-107860.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c49621b7c2488..2c9d908166fa3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -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; - - 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 { + hir::FnRetTy::Return(hir_ty) => { + let span = hir_ty.span; + + 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); diff --git a/tests/ui/suggestions/issue-107860.rs b/tests/ui/suggestions/issue-107860.rs new file mode 100644 index 0000000000000..a6449cd44d0f8 --- /dev/null +++ b/tests/ui/suggestions/issue-107860.rs @@ -0,0 +1,6 @@ +// edition: 2021 + +async fn str(T: &str) -> &str { &str } +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/suggestions/issue-107860.stderr b/tests/ui/suggestions/issue-107860.stderr new file mode 100644 index 0000000000000..92e3cf8c43b3b --- /dev/null +++ b/tests/ui/suggestions/issue-107860.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-107860.rs:3:36 + | +LL | async fn str(T: &str) -> &str { &str } + | ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<...>}` + | + = note: expected reference `&str` + found reference `&for<'a> fn(&'a str) -> impl Future {str::<_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.