From 60da5de1c68e8465f4896f8cd5a8b158c00051a1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 16 Mar 2023 04:02:56 +0000 Subject: [PATCH 01/14] Fix index out of bounds in suggest_trait_fn_ty_for_impl_fn_infer --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 9 ++++++--- tests/ui/suggestions/bad-infer-in-trait-impl.rs | 10 ++++++++++ .../ui/suggestions/bad-infer-in-trait-impl.stderr | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/ui/suggestions/bad-infer-in-trait-impl.rs create mode 100644 tests/ui/suggestions/bad-infer-in-trait-impl.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index f830269b45d..3c2cf0d80ab 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -3317,10 +3317,13 @@ fn suggest_trait_fn_ty_for_impl_fn_infer( tcx, trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)), ); + let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig); - let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() }; - - Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty)) + Some(if let Some(arg_idx) = arg_idx { + *fn_sig.inputs().get(arg_idx)? + } else { + fn_sig.output() + }) } #[instrument(level = "trace", skip(self, generate_err))] diff --git a/tests/ui/suggestions/bad-infer-in-trait-impl.rs b/tests/ui/suggestions/bad-infer-in-trait-impl.rs new file mode 100644 index 00000000000..87db2636fb2 --- /dev/null +++ b/tests/ui/suggestions/bad-infer-in-trait-impl.rs @@ -0,0 +1,10 @@ +trait Foo { + fn bar(); +} + +impl Foo for () { + fn bar(s: _) {} + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +fn main() {} diff --git a/tests/ui/suggestions/bad-infer-in-trait-impl.stderr b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr new file mode 100644 index 00000000000..418690ff85f --- /dev/null +++ b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr @@ -0,0 +1,14 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-infer-in-trait-impl.rs:6:15 + | +LL | fn bar(s: _) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn bar(s: T) {} + | +++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. From dc39bf8efc06bda8f510d1d64ce3302acc7ac0a3 Mon Sep 17 00:00:00 2001 From: Jamilya Shurukhova Date: Thu, 16 Mar 2023 10:18:31 +0100 Subject: [PATCH 02/14] E0206 - added `union` to description --- compiler/rustc_error_codes/src/error_codes/E0206.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md index 4405a2149ce..a0a6c0ffdce 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0206.md +++ b/compiler/rustc_error_codes/src/error_codes/E0206.md @@ -1,5 +1,5 @@ The `Copy` trait was implemented on a type which is neither a struct nor an -enum. +enum nor a union. Erroneous code example: @@ -10,6 +10,6 @@ struct Bar; impl Copy for &'static mut Bar { } // error! ``` -You can only implement `Copy` for a struct or an enum. +You can only implement `Copy` for a struct, a union, or an enum. The previous example will fail because `&'static mut Bar` is not a struct or enum. From 1f12c3e397dd36c8ad7ea376f7e5a2aaaa3b7a26 Mon Sep 17 00:00:00 2001 From: Jamilya Shurukhova Date: Thu, 16 Mar 2023 10:26:34 +0100 Subject: [PATCH 03/14] E0206 - removed space --- compiler/rustc_error_codes/src/error_codes/E0206.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md index a0a6c0ffdce..b3e5d6e28d8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0206.md +++ b/compiler/rustc_error_codes/src/error_codes/E0206.md @@ -1,5 +1,4 @@ -The `Copy` trait was implemented on a type which is neither a struct nor an -enum nor a union. +The `Copy` trait was implemented on a type which is neither a struct nor an enum nor a union. Erroneous code example: From 827a990255b49a5a6eee67844fbbeaeb323236b4 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 16 Mar 2023 23:17:56 +0800 Subject: [PATCH 04/14] Do not ICE for unexpected lifetime with ConstGeneric rib --- compiler/rustc_resolve/src/late.rs | 5 +++-- .../ui/lifetimes/unusual-rib-combinations.rs | 5 +++++ .../lifetimes/unusual-rib-combinations.stderr | 21 +++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index eff10e5af9f..1afd8851ce0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1478,8 +1478,9 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti } else { LifetimeUseSet::Many }), - LifetimeRibKind::Generics { .. } => None, - LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => { + LifetimeRibKind::Generics { .. } + | LifetimeRibKind::ConstGeneric => None, + LifetimeRibKind::AnonConst => { span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind) } }) diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs index 1c122f42e59..0ae68ad04f7 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.rs +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -25,4 +25,9 @@ fn d() {} //~^ ERROR missing lifetime specifier //~| ERROR `S<'_>` is forbidden as the type of a const generic parameter +trait Foo<'a> {} +struct Bar Foo<'a>)>; +//~^ ERROR use of non-static lifetime `'a` in const generic +//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter + fn main() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 68f4fce0178..20163d289b1 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -9,6 +9,14 @@ help: consider introducing a named lifetime parameter LL | fn d<'a, const C: S<'a>>() {} | +++ ++++ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/unusual-rib-combinations.rs:29:22 + | +LL | struct Bar Foo<'a>)>; + | ^^ + | + = note: for more information, see issue #74052 + error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/unusual-rib-combinations.rs:7:16 | @@ -55,7 +63,16 @@ LL | fn d() {} = note: the only supported types are integers, `bool` and `char` = help: more complex types are supported with `#![feature(adt_const_params)]` -error: aborting due to 7 previous errors +error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter + --> $DIR/unusual-rib-combinations.rs:29:21 + | +LL | struct Bar Foo<'a>)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` -Some errors have detailed explanations: E0106, E0214, E0308. +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0106, E0214, E0308, E0771. For more information about an error, try `rustc --explain E0106`. From 2dbda0af15f95c5e816f9357c59fad3576e1a45a Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki Date: Thu, 16 Mar 2023 15:08:14 -0700 Subject: [PATCH 05/14] fallback to lstat when stat fails on Windows --- library/std/src/sys/windows/fs.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index d2c597664fa..a4161c1c3c4 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1236,7 +1236,19 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { } pub fn stat(path: &Path) -> io::Result { - metadata(path, ReparsePoint::Follow) + match metadata(path, ReparsePoint::Follow) { + Err(err) => { + if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) { + if let Ok(attrs) = lstat(path) { + if !attrs.file_type().is_symlink() { + return Ok(attrs); + } + } + } + Err(err) + }, + Ok(attrs) => Ok(attrs), + } } pub fn lstat(path: &Path) -> io::Result { From 0aad0b32ae05d7d03d0c18c7083edf02c7e3f857 Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki Date: Thu, 16 Mar 2023 17:07:41 -0700 Subject: [PATCH 06/14] run rustfmt on changes --- library/std/src/sys/windows/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index a4161c1c3c4..ef8f73645be 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1246,7 +1246,7 @@ pub fn stat(path: &Path) -> io::Result { } } Err(err) - }, + } Ok(attrs) => Ok(attrs), } } From 550e3087d1b521f2b3b669ebaaf6d16e4c593fca Mon Sep 17 00:00:00 2001 From: Mu42 Date: Fri, 17 Mar 2023 14:36:22 +0800 Subject: [PATCH 07/14] Suggest surrounding the macro with `{}` to interpret as a statement --- compiler/rustc_expand/src/mbe/diagnostics.rs | 24 +++++++++++++++----- tests/ui/macros/issue-109237.rs | 7 ++++++ tests/ui/macros/issue-109237.stderr | 18 +++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 tests/ui/macros/issue-109237.rs create mode 100644 tests/ui/macros/issue-109237.stderr diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index b1d9cea2773..6bc393c6534 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -245,12 +245,24 @@ pub(super) fn emit_frag_parse_err( e.note( "the macro call doesn't expand to an expression, but it can expand to a statement", ); - e.span_suggestion_verbose( - site_span.shrink_to_hi(), - "add `;` to interpret the expansion as a statement", - ";", - Applicability::MaybeIncorrect, - ); + + if parser.token == token::Semi { + if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) { + e.span_suggestion_verbose( + site_span, + "surround the macro invocation with `{}` to interpret the expansion as a statement", + format!("{{ {}; }}", snippet), + Applicability::MaybeIncorrect, + ); + } + } else { + e.span_suggestion_verbose( + site_span.shrink_to_hi(), + "add `;` to interpret the expansion as a statement", + ";", + Applicability::MaybeIncorrect, + ); + } } }, _ => annotate_err_with_kind(&mut e, kind, site_span), diff --git a/tests/ui/macros/issue-109237.rs b/tests/ui/macros/issue-109237.rs new file mode 100644 index 00000000000..86a193c9e44 --- /dev/null +++ b/tests/ui/macros/issue-109237.rs @@ -0,0 +1,7 @@ +macro_rules! statement { + () => {;}; //~ ERROR expected expression +} + +fn main() { + let _ = statement!(); +} diff --git a/tests/ui/macros/issue-109237.stderr b/tests/ui/macros/issue-109237.stderr new file mode 100644 index 00000000000..d125cff63ea --- /dev/null +++ b/tests/ui/macros/issue-109237.stderr @@ -0,0 +1,18 @@ +error: expected expression, found `;` + --> $DIR/issue-109237.rs:2:12 + | +LL | () => {;}; + | ^ expected expression +... +LL | let _ = statement!(); + | ------------ in this macro invocation + | + = note: the macro call doesn't expand to an expression, but it can expand to a statement + = note: this error originates in the macro `statement` (in Nightly builds, run with -Z macro-backtrace for more info) +help: surround the macro invocation with `{}` to interpret the expansion as a statement + | +LL | let _ = { statement!(); }; + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + From 97740a648f57e24c45f641f2827598b26a2bf661 Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki Date: Fri, 17 Mar 2023 02:33:31 -0700 Subject: [PATCH 08/14] Check for llvm-tools before install --- src/bootstrap/install.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index ac3843c3344..42d895a3413 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -210,10 +210,13 @@ fn run($sel, $builder: &Builder<'_>) { } }; LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, { - let tarball = builder - .ensure(dist::LlvmTools { target: self.target }) - .expect("missing llvm-tools"); - install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball); + if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) { + install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball); + } else { + builder.info( + &format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target), + ); + } }; Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, { if let Some(tarball) = builder.ensure(dist::Rustfmt { From 2a5208011d2a78d441bb72492812f618a8c24cfb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 17 Mar 2023 13:34:15 +0400 Subject: [PATCH 09/14] resolve: Improve debug impls for `NameBinding` Print at least the Some/None/Ok/Err status of the nested bindings if not the bindings themselves. --- compiler/rustc_resolve/src/imports.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 5d40c6e4e48..6e27bcc5bf3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -85,20 +85,28 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Single { ref source, ref target, + ref source_bindings, + ref target_bindings, ref type_ns_only, ref nested, ref id, - // Ignore the following to avoid an infinite loop while printing. - source_bindings: _, - target_bindings: _, } => f .debug_struct("Single") .field("source", source) .field("target", target) + // Ignore the nested bindings to avoid an infinite loop while printing. + .field( + "source_bindings", + &source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))), + ) + .field( + "target_bindings", + &target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))), + ) .field("type_ns_only", type_ns_only) .field("nested", nested) .field("id", id) - .finish_non_exhaustive(), + .finish(), Glob { ref is_prelude, ref max_vis, ref id } => f .debug_struct("Glob") .field("is_prelude", is_prelude) From 05dc132adb94c0583423ea0cbe25c67af4fdb1dd Mon Sep 17 00:00:00 2001 From: Jamilya Shurukhova Date: Fri, 17 Mar 2023 14:54:39 +0100 Subject: [PATCH 10/14] E0206 - code review changes --- compiler/rustc_error_codes/src/error_codes/E0206.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md index b3e5d6e28d8..8658b5a858a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0206.md +++ b/compiler/rustc_error_codes/src/error_codes/E0206.md @@ -1,4 +1,5 @@ -The `Copy` trait was implemented on a type which is neither a struct nor an enum nor a union. +The `Copy` trait was implemented on a type which is neither a struct, an +enum, nor a union. Erroneous code example: @@ -9,6 +10,6 @@ struct Bar; impl Copy for &'static mut Bar { } // error! ``` -You can only implement `Copy` for a struct, a union, or an enum. +You can only implement `Copy` for a struct, an enum, or a union. The previous example will fail because `&'static mut Bar` -is not a struct or enum. +is not a struct, an enum, or a union. From c4bb47ac36aa3975160ba8fb72978202e436a2f9 Mon Sep 17 00:00:00 2001 From: Jamilya Shurukhova Date: Fri, 17 Mar 2023 15:50:37 +0100 Subject: [PATCH 11/14] Update compiler/rustc_error_codes/src/error_codes/E0206.md Co-authored-by: Waffle Maybe --- compiler/rustc_error_codes/src/error_codes/E0206.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md index 8658b5a858a..9e85234bdbb 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0206.md +++ b/compiler/rustc_error_codes/src/error_codes/E0206.md @@ -1,4 +1,4 @@ -The `Copy` trait was implemented on a type which is neither a struct, an +The `Copy` trait was implemented on a type which is neither a struct, an enum, nor a union. Erroneous code example: From 79ad7cca453468458a0ae63d091cbe6b23aa94a1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 Mar 2023 20:37:04 +0000 Subject: [PATCH 12/14] Erase escaping late-bound regions when probing for ambiguous associated types --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 17 ++++++++++++++--- .../non_lifetime_binders/missing-assoc-item.rs | 11 +++++++++++ .../missing-assoc-item.stderr | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs create mode 100644 tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index f830269b45d..d820a3da555 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2396,13 +2396,24 @@ fn probe_traits_that_match_assoc_ty( tcx, infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id), ); + // I guess we don't need to make a universe unless we need it, + // but also we're on the error path, so it doesn't matter here. + let universe = infcx.create_next_universe(); infcx .can_eq( ty::ParamEnv::empty(), impl_.self_ty(), - // Must fold past escaping bound vars too, - // since we have those at this point in astconv. - tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased), + tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate { + regions: &mut |_| tcx.lifetimes.re_erased, + types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType { + universe, + name: bv.kind, + }), + consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst { + universe, + name: bv + }, ty), + }) ) }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs new file mode 100644 index 00000000000..50f0152e904 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs @@ -0,0 +1,11 @@ +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +fn f() +where + for B::Item: Send, + //~^ ERROR ambiguous associated type +{ +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr new file mode 100644 index 00000000000..be6955c111e --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr @@ -0,0 +1,18 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/missing-assoc-item.rs:1:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0223]: ambiguous associated type + --> $DIR/missing-assoc-item.rs:6:12 + | +LL | for B::Item: Send, + | ^^^^^^^ help: use the fully-qualified path: `::Item` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0223`. From 08c913279fc21e57acd210a98dfdfd740e86b565 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 17 Mar 2023 03:14:27 +0000 Subject: [PATCH 13/14] Pass the right HIR back from get_fn_decl --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 19 +++--- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 61 +++++++++++++------ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 3 +- .../suggest-ret-on-async-w-late.rs | 11 ++++ .../suggest-ret-on-async-w-late.stderr | 11 ++++ 8 files changed, 75 insertions(+), 36 deletions(-) create mode 100644 tests/ui/suggestions/suggest-ret-on-async-w-late.rs create mode 100644 tests/ui/suggestions/suggest-ret-on-async-w-late.stderr diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index e19ef2ff3bf..035ccf30b24 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -299,7 +299,7 @@ fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Spa { // check that the `if` expr without `else` is the fn body's expr if expr.span == sp { - return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| { + return self.get_fn_decl(hir_id).and_then(|(_, fn_decl, _)| { let span = fn_decl.output.span(); let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?; Some((span, format!("expected `{snippet}` because of this return type"))) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 3d6274ede81..a27905ea46c 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1722,12 +1722,13 @@ fn report_return_mismatched_types<'a>( fcx.suggest_semicolon_at_end(cond_expr.span, &mut err); } } - fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main)) + fcx.get_node_fn_decl(parent) + .map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main)) } else { fcx.get_fn_decl(parent_id) }; - if let Some((fn_decl, can_suggest)) = fn_decl { + if let Some((fn_id, fn_decl, can_suggest)) = fn_decl { if blk_id.is_none() { pointing_at_return_type |= fcx.suggest_missing_return_type( &mut err, @@ -1735,7 +1736,7 @@ fn report_return_mismatched_types<'a>( expected, found, can_suggest, - fcx.tcx.hir().get_parent_item(id).into(), + fn_id, ); } if !pointing_at_return_type { @@ -1746,17 +1747,11 @@ fn report_return_mismatched_types<'a>( let parent_id = fcx.tcx.hir().get_parent_item(id); let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id); - if let (Some(expr), Some(_), Some((fn_decl, _, _))) = + if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) = (expression, blk_id, fcx.get_node_fn_decl(parent_item)) { fcx.suggest_missing_break_or_return_expr( - &mut err, - expr, - fn_decl, - expected, - found, - id, - parent_id.into(), + &mut err, expr, fn_decl, expected, found, id, fn_id, ); } @@ -1882,7 +1877,7 @@ fn add_impl_trait_explanation<'a>( } fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { - if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) + if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id) && let hir::FnRetTy::Return(ty) = fn_decl.output && let ty = fcx.astconv().ast_ty_to_ty( ty) && let ty::Dynamic(..) = ty.kind() diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index afef331ec1d..d64b5728f32 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -799,7 +799,7 @@ fn check_expr_return( self.ret_coercion_span.set(Some(expr.span)); } let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) { + if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { coercion.coerce_forced_unit( self, &cause, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e539693402a..8455076de56 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -898,51 +898,74 @@ pub fn resolve_ty_and_res_fully_qualified_call( ) } - /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise. + /// Given a function `Node`, return its `HirId` and `FnDecl` if it exists. Given a closure + /// that is the child of a function, return that function's `HirId` and `FnDecl` instead. + /// This may seem confusing at first, but this is used in diagnostics for `async fn`, + /// for example, where most of the type checking actually happens within a nested closure, + /// but we often want access to the parent function's signature. + /// + /// Otherwise, return false. pub(in super::super) fn get_node_fn_decl( &self, node: Node<'tcx>, - ) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident, bool)> { + ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> { match node { - Node::Item(&hir::Item { ident, kind: hir::ItemKind::Fn(ref sig, ..), .. }) => { + Node::Item(&hir::Item { + ident, + kind: hir::ItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => { // This is less than ideal, it will not suggest a return type span on any // method called `main`, regardless of whether it is actually the entry point, // but it will still present it as the reason for the expected type. - Some((&sig.decl, ident, ident.name != sym::main)) + Some(( + hir::HirId::make_owner(owner_id.def_id), + &sig.decl, + ident, + ident.name != sym::main, + )) } Node::TraitItem(&hir::TraitItem { ident, kind: hir::TraitItemKind::Fn(ref sig, ..), + owner_id, .. - }) => Some((&sig.decl, ident, true)), + }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, true)), Node::ImplItem(&hir::ImplItem { ident, kind: hir::ImplItemKind::Fn(ref sig, ..), + owner_id, .. - }) => Some((&sig.decl, ident, false)), - Node::Expr(&hir::Expr { - hir_id, - kind: hir::ExprKind::Closure(..), - .. - }) if let Some(Node::Item(&hir::Item { + }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)), + Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(..), .. }) + if let Some(Node::Item(&hir::Item { + ident, + kind: hir::ItemKind::Fn(ref sig, ..), + owner_id, + .. + })) = self.tcx.hir().find_parent(hir_id) => Some(( + hir::HirId::make_owner(owner_id.def_id), + &sig.decl, ident, - kind: hir::ItemKind::Fn(ref sig, ..), - .. - })) = self.tcx.hir().find_parent(hir_id) => { - Some((&sig.decl, ident, ident.name != sym::main)) - }, + ident.name != sym::main, + )), _ => None, } } - /// Given a `HirId`, return the `FnDecl` of the method it is enclosed by and whether a + /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a /// suggestion can be made, `None` otherwise. - pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, bool)> { + pub fn get_fn_decl( + &self, + blk_id: hir::HirId, + ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, bool)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or // `while` before reaching it, as block tail returns are not available in them. self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| { let parent = self.tcx.hir().get(blk_id); - self.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main)) + self.get_node_fn_decl(parent) + .map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main)) }) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7064ff65384..61338ac613a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1669,7 +1669,7 @@ fn parent_item_span(&self, id: hir::HirId) -> Option { /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id); - self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident)) + self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident)) } /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 690d8a23826..7a09ea40d79 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -64,8 +64,7 @@ pub fn suggest_mismatched_types_on_tail( let expr = expr.peel_drop_temps(); self.suggest_missing_semicolon(err, expr, expected, false); let mut pointing_at_return_type = false; - if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { - let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type( err, &fn_decl, diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs new file mode 100644 index 00000000000..459b94f943b --- /dev/null +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs @@ -0,0 +1,11 @@ +// edition: 2021 + +// Make sure we don't ICE when suggesting a return type +// for an async fn that has late-bound vars... + +async fn ice(_: &i32) { + true + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr new file mode 100644 index 00000000000..bff864b222b --- /dev/null +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/suggest-ret-on-async-w-late.rs:7:5 + | +LL | async fn ice(_: &i32) { + | - help: try adding a return type: `-> bool` +LL | true + | ^^^^ expected `()`, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 32c589b2363eb96649e5692b4b335777dbeb2f9d Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki Date: Fri, 17 Mar 2023 10:44:22 -0700 Subject: [PATCH 14/14] Modify code style as per comments --- library/std/src/sys/windows/fs.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index ef8f73645be..373157bd9e8 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1237,17 +1237,15 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { pub fn stat(path: &Path) -> io::Result { match metadata(path, ReparsePoint::Follow) { - Err(err) => { - if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) { - if let Ok(attrs) = lstat(path) { - if !attrs.file_type().is_symlink() { - return Ok(attrs); - } + Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { + if let Ok(attrs) = lstat(path) { + if !attrs.file_type().is_symlink() { + return Ok(attrs); } } Err(err) } - Ok(attrs) => Ok(attrs), + result => result, } }