Skip to content

Commit 85123d2

Browse files
committed
Auto merge of rust-lang#109284 - matthiaskrgr:rollup-aaublsx, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#109102 (Erase escaping late-bound regions when probing for ambiguous associated types) - rust-lang#109200 (Fix index out of bounds in `suggest_trait_fn_ty_for_impl_fn_infer`) - rust-lang#109211 (E0206 - update description ) - rust-lang#109222 (Do not ICE for unexpected lifetime with ConstGeneric rib) - rust-lang#109235 (fallback to lstat when stat fails on Windows) - rust-lang#109248 (Pass the right HIR back from `get_fn_decl`) - rust-lang#109251 (Suggest surrounding the macro with `{}` to interpret as a statement) - rust-lang#109256 (Check for llvm-tools before install) - rust-lang#109257 (resolve: Improve debug impls for `NameBinding`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 13afbda + 0d4a56c commit 85123d2

File tree

23 files changed

+252
-65
lines changed

23 files changed

+252
-65
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
The `Copy` trait was implemented on a type which is neither a struct nor an
2-
enum.
1+
The `Copy` trait was implemented on a type which is neither a struct, an
2+
enum, nor a union.
33

44
Erroneous code example:
55

@@ -10,6 +10,6 @@ struct Bar;
1010
impl Copy for &'static mut Bar { } // error!
1111
```
1212

13-
You can only implement `Copy` for a struct or an enum.
13+
You can only implement `Copy` for a struct, an enum, or a union.
1414
The previous example will fail because `&'static mut Bar`
15-
is not a struct or enum.
15+
is not a struct, an enum, or a union.

compiler/rustc_expand/src/mbe/diagnostics.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,24 @@ pub(super) fn emit_frag_parse_err(
245245
e.note(
246246
"the macro call doesn't expand to an expression, but it can expand to a statement",
247247
);
248-
e.span_suggestion_verbose(
249-
site_span.shrink_to_hi(),
250-
"add `;` to interpret the expansion as a statement",
251-
";",
252-
Applicability::MaybeIncorrect,
253-
);
248+
249+
if parser.token == token::Semi {
250+
if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) {
251+
e.span_suggestion_verbose(
252+
site_span,
253+
"surround the macro invocation with `{}` to interpret the expansion as a statement",
254+
format!("{{ {}; }}", snippet),
255+
Applicability::MaybeIncorrect,
256+
);
257+
}
258+
} else {
259+
e.span_suggestion_verbose(
260+
site_span.shrink_to_hi(),
261+
"add `;` to interpret the expansion as a statement",
262+
";",
263+
Applicability::MaybeIncorrect,
264+
);
265+
}
254266
}
255267
},
256268
_ => annotate_err_with_kind(&mut e, kind, site_span),

compiler/rustc_hir_analysis/src/astconv/mod.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -2396,13 +2396,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23962396
tcx,
23972397
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
23982398
);
2399+
// I guess we don't need to make a universe unless we need it,
2400+
// but also we're on the error path, so it doesn't matter here.
2401+
let universe = infcx.create_next_universe();
23992402
infcx
24002403
.can_eq(
24012404
ty::ParamEnv::empty(),
24022405
impl_.self_ty(),
2403-
// Must fold past escaping bound vars too,
2404-
// since we have those at this point in astconv.
2405-
tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
2406+
tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate {
2407+
regions: &mut |_| tcx.lifetimes.re_erased,
2408+
types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
2409+
universe,
2410+
name: bv.kind,
2411+
}),
2412+
consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
2413+
universe,
2414+
name: bv
2415+
}, ty),
2416+
})
24062417
)
24072418
})
24082419
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
@@ -3317,10 +3328,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
33173328
tcx,
33183329
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
33193330
);
3331+
let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
33203332

3321-
let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
3322-
3323-
Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty))
3333+
Some(if let Some(arg_idx) = arg_idx {
3334+
*fn_sig.inputs().get(arg_idx)?
3335+
} else {
3336+
fn_sig.output()
3337+
})
33243338
}
33253339

33263340
#[instrument(level = "trace", skip(self, generate_err))]

compiler/rustc_hir_typeck/src/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
299299
{
300300
// check that the `if` expr without `else` is the fn body's expr
301301
if expr.span == sp {
302-
return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
302+
return self.get_fn_decl(hir_id).and_then(|(_, fn_decl, _)| {
303303
let span = fn_decl.output.span();
304304
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
305305
Some((span, format!("expected `{snippet}` because of this return type")))

compiler/rustc_hir_typeck/src/coercion.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -1722,20 +1722,21 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17221722
fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
17231723
}
17241724
}
1725-
fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
1725+
fcx.get_node_fn_decl(parent)
1726+
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
17261727
} else {
17271728
fcx.get_fn_decl(parent_id)
17281729
};
17291730

1730-
if let Some((fn_decl, can_suggest)) = fn_decl {
1731+
if let Some((fn_id, fn_decl, can_suggest)) = fn_decl {
17311732
if blk_id.is_none() {
17321733
pointing_at_return_type |= fcx.suggest_missing_return_type(
17331734
&mut err,
17341735
&fn_decl,
17351736
expected,
17361737
found,
17371738
can_suggest,
1738-
fcx.tcx.hir().get_parent_item(id).into(),
1739+
fn_id,
17391740
);
17401741
}
17411742
if !pointing_at_return_type {
@@ -1746,17 +1747,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17461747
let parent_id = fcx.tcx.hir().get_parent_item(id);
17471748
let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id);
17481749

1749-
if let (Some(expr), Some(_), Some((fn_decl, _, _))) =
1750+
if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) =
17501751
(expression, blk_id, fcx.get_node_fn_decl(parent_item))
17511752
{
17521753
fcx.suggest_missing_break_or_return_expr(
1753-
&mut err,
1754-
expr,
1755-
fn_decl,
1756-
expected,
1757-
found,
1758-
id,
1759-
parent_id.into(),
1754+
&mut err, expr, fn_decl, expected, found, id, fn_id,
17601755
);
17611756
}
17621757

@@ -1882,7 +1877,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18821877
}
18831878

18841879
fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
1885-
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
1880+
if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
18861881
&& let hir::FnRetTy::Return(ty) = fn_decl.output
18871882
&& let ty = fcx.astconv().ast_ty_to_ty( ty)
18881883
&& let ty::Dynamic(..) = ty.kind()

compiler/rustc_hir_typeck/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
788788
self.ret_coercion_span.set(Some(expr.span));
789789
}
790790
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
791-
if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
791+
if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
792792
coercion.coerce_forced_unit(
793793
self,
794794
&cause,

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+42-19
Original file line numberDiff line numberDiff line change
@@ -898,51 +898,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
898898
)
899899
}
900900

901-
/// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
901+
/// Given a function `Node`, return its `HirId` and `FnDecl` if it exists. Given a closure
902+
/// that is the child of a function, return that function's `HirId` and `FnDecl` instead.
903+
/// This may seem confusing at first, but this is used in diagnostics for `async fn`,
904+
/// for example, where most of the type checking actually happens within a nested closure,
905+
/// but we often want access to the parent function's signature.
906+
///
907+
/// Otherwise, return false.
902908
pub(in super::super) fn get_node_fn_decl(
903909
&self,
904910
node: Node<'tcx>,
905-
) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident, bool)> {
911+
) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
906912
match node {
907-
Node::Item(&hir::Item { ident, kind: hir::ItemKind::Fn(ref sig, ..), .. }) => {
913+
Node::Item(&hir::Item {
914+
ident,
915+
kind: hir::ItemKind::Fn(ref sig, ..),
916+
owner_id,
917+
..
918+
}) => {
908919
// This is less than ideal, it will not suggest a return type span on any
909920
// method called `main`, regardless of whether it is actually the entry point,
910921
// but it will still present it as the reason for the expected type.
911-
Some((&sig.decl, ident, ident.name != sym::main))
922+
Some((
923+
hir::HirId::make_owner(owner_id.def_id),
924+
&sig.decl,
925+
ident,
926+
ident.name != sym::main,
927+
))
912928
}
913929
Node::TraitItem(&hir::TraitItem {
914930
ident,
915931
kind: hir::TraitItemKind::Fn(ref sig, ..),
932+
owner_id,
916933
..
917-
}) => Some((&sig.decl, ident, true)),
934+
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, true)),
918935
Node::ImplItem(&hir::ImplItem {
919936
ident,
920937
kind: hir::ImplItemKind::Fn(ref sig, ..),
938+
owner_id,
921939
..
922-
}) => Some((&sig.decl, ident, false)),
923-
Node::Expr(&hir::Expr {
924-
hir_id,
925-
kind: hir::ExprKind::Closure(..),
926-
..
927-
}) if let Some(Node::Item(&hir::Item {
940+
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
941+
Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(..), .. })
942+
if let Some(Node::Item(&hir::Item {
943+
ident,
944+
kind: hir::ItemKind::Fn(ref sig, ..),
945+
owner_id,
946+
..
947+
})) = self.tcx.hir().find_parent(hir_id) => Some((
948+
hir::HirId::make_owner(owner_id.def_id),
949+
&sig.decl,
928950
ident,
929-
kind: hir::ItemKind::Fn(ref sig, ..),
930-
..
931-
})) = self.tcx.hir().find_parent(hir_id) => {
932-
Some((&sig.decl, ident, ident.name != sym::main))
933-
},
951+
ident.name != sym::main,
952+
)),
934953
_ => None,
935954
}
936955
}
937956

938-
/// Given a `HirId`, return the `FnDecl` of the method it is enclosed by and whether a
957+
/// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a
939958
/// suggestion can be made, `None` otherwise.
940-
pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, bool)> {
959+
pub fn get_fn_decl(
960+
&self,
961+
blk_id: hir::HirId,
962+
) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, bool)> {
941963
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
942964
// `while` before reaching it, as block tail returns are not available in them.
943965
self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
944966
let parent = self.tcx.hir().get(blk_id);
945-
self.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
967+
self.get_node_fn_decl(parent)
968+
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
946969
})
947970
}
948971

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16691669
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
16701670
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
16711671
let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
1672-
self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
1672+
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
16731673
}
16741674

16751675
/// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6464
let expr = expr.peel_drop_temps();
6565
self.suggest_missing_semicolon(err, expr, expected, false);
6666
let mut pointing_at_return_type = false;
67-
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
68-
let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
67+
if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
6968
pointing_at_return_type = self.suggest_missing_return_type(
7069
err,
7170
&fn_decl,

compiler/rustc_resolve/src/imports.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,28 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
8585
Single {
8686
ref source,
8787
ref target,
88+
ref source_bindings,
89+
ref target_bindings,
8890
ref type_ns_only,
8991
ref nested,
9092
ref id,
91-
// Ignore the following to avoid an infinite loop while printing.
92-
source_bindings: _,
93-
target_bindings: _,
9493
} => f
9594
.debug_struct("Single")
9695
.field("source", source)
9796
.field("target", target)
97+
// Ignore the nested bindings to avoid an infinite loop while printing.
98+
.field(
99+
"source_bindings",
100+
&source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
101+
)
102+
.field(
103+
"target_bindings",
104+
&target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
105+
)
98106
.field("type_ns_only", type_ns_only)
99107
.field("nested", nested)
100108
.field("id", id)
101-
.finish_non_exhaustive(),
109+
.finish(),
102110
Glob { ref is_prelude, ref max_vis, ref id } => f
103111
.debug_struct("Glob")
104112
.field("is_prelude", is_prelude)

compiler/rustc_resolve/src/late.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
14781478
} else {
14791479
LifetimeUseSet::Many
14801480
}),
1481-
LifetimeRibKind::Generics { .. } => None,
1482-
LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
1481+
LifetimeRibKind::Generics { .. }
1482+
| LifetimeRibKind::ConstGeneric => None,
1483+
LifetimeRibKind::AnonConst => {
14831484
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
14841485
}
14851486
})

library/std/src/sys/windows/fs.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,17 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
12361236
}
12371237

12381238
pub fn stat(path: &Path) -> io::Result<FileAttr> {
1239-
metadata(path, ReparsePoint::Follow)
1239+
match metadata(path, ReparsePoint::Follow) {
1240+
Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => {
1241+
if let Ok(attrs) = lstat(path) {
1242+
if !attrs.file_type().is_symlink() {
1243+
return Ok(attrs);
1244+
}
1245+
}
1246+
Err(err)
1247+
}
1248+
result => result,
1249+
}
12401250
}
12411251

12421252
pub fn lstat(path: &Path) -> io::Result<FileAttr> {

src/bootstrap/install.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,13 @@ install!((self, builder, _config),
210210
}
211211
};
212212
LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
213-
let tarball = builder
214-
.ensure(dist::LlvmTools { target: self.target })
215-
.expect("missing llvm-tools");
216-
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
213+
if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
214+
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
215+
} else {
216+
builder.info(
217+
&format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target),
218+
);
219+
}
217220
};
218221
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
219222
if let Some(tarball) = builder.ensure(dist::Rustfmt {

tests/ui/lifetimes/unusual-rib-combinations.rs

+5
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,9 @@ fn d<const C: S>() {}
2525
//~^ ERROR missing lifetime specifier
2626
//~| ERROR `S<'_>` is forbidden as the type of a const generic parameter
2727

28+
trait Foo<'a> {}
29+
struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
30+
//~^ ERROR use of non-static lifetime `'a` in const generic
31+
//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
32+
2833
fn main() {}

0 commit comments

Comments
 (0)