Skip to content

Commit 93e7cb8

Browse files
committed
Auto merge of #125415 - fmease:rollup-n2bg7q5, r=fmease
Rollup of 5 pull requests Successful merges: - #124896 (miri: rename intrinsic_fallback_checks_ub to intrinsic_fallback_is_spec) - #125015 (Pattern types: Prohibit generic args on const params) - #125049 (Disallow cast with trailing braced macro in let-else) - #125259 (An async closure may implement `FnMut`/`Fn` if it has no self-borrows) - #125296 (Fix `unexpected_cfgs` lint on std) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 22f5bdc + 8219fd2 commit 93e7cb8

File tree

23 files changed

+406
-353
lines changed

23 files changed

+406
-353
lines changed

compiler/rustc_ast/src/util/classify.rs

+91-4
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,17 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
8181
}
8282
}
8383

84+
pub enum TrailingBrace<'a> {
85+
/// Trailing brace in a macro call, like the one in `x as *const brace! {}`.
86+
/// We will suggest changing the macro call to a different delimiter.
87+
MacCall(&'a ast::MacCall),
88+
/// Trailing brace in any other expression, such as `a + B {}`. We will
89+
/// suggest wrapping the innermost expression in parentheses: `a + (B {})`.
90+
Expr(&'a ast::Expr),
91+
}
92+
8493
/// If an expression ends with `}`, returns the innermost expression ending in the `}`
85-
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
94+
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
8695
loop {
8796
match &expr.kind {
8897
AddrOf(_, _, e)
@@ -111,10 +120,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
111120
| Struct(..)
112121
| TryBlock(..)
113122
| While(..)
114-
| ConstBlock(_) => break Some(expr),
123+
| ConstBlock(_) => break Some(TrailingBrace::Expr(expr)),
124+
125+
Cast(_, ty) => {
126+
break type_trailing_braced_mac_call(ty).map(TrailingBrace::MacCall);
127+
}
115128

116129
MacCall(mac) => {
117-
break (mac.args.delim == Delimiter::Brace).then_some(expr);
130+
break (mac.args.delim == Delimiter::Brace).then_some(TrailingBrace::MacCall(mac));
118131
}
119132

120133
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
@@ -131,7 +144,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
131144
| MethodCall(_)
132145
| Tup(_)
133146
| Lit(_)
134-
| Cast(_, _)
135147
| Type(_, _)
136148
| Await(_, _)
137149
| Field(_, _)
@@ -148,3 +160,78 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
148160
}
149161
}
150162
}
163+
164+
/// If the type's last token is `}`, it must be due to a braced macro call, such
165+
/// as in `*const brace! { ... }`. Returns that trailing macro call.
166+
fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
167+
loop {
168+
match &ty.kind {
169+
ast::TyKind::MacCall(mac) => {
170+
break (mac.args.delim == Delimiter::Brace).then_some(mac);
171+
}
172+
173+
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
174+
ty = &mut_ty.ty;
175+
}
176+
177+
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
178+
ast::FnRetTy::Default(_) => break None,
179+
ast::FnRetTy::Ty(ret) => ty = ret,
180+
},
181+
182+
ast::TyKind::Path(_, path) => match path_return_type(path) {
183+
Some(trailing_ty) => ty = trailing_ty,
184+
None => break None,
185+
},
186+
187+
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds, _) => {
188+
match bounds.last() {
189+
Some(ast::GenericBound::Trait(bound, _)) => {
190+
match path_return_type(&bound.trait_ref.path) {
191+
Some(trailing_ty) => ty = trailing_ty,
192+
None => break None,
193+
}
194+
}
195+
Some(ast::GenericBound::Outlives(_)) | None => break None,
196+
}
197+
}
198+
199+
ast::TyKind::Slice(..)
200+
| ast::TyKind::Array(..)
201+
| ast::TyKind::Never
202+
| ast::TyKind::Tup(..)
203+
| ast::TyKind::Paren(..)
204+
| ast::TyKind::Typeof(..)
205+
| ast::TyKind::Infer
206+
| ast::TyKind::ImplicitSelf
207+
| ast::TyKind::CVarArgs
208+
| ast::TyKind::Pat(..)
209+
| ast::TyKind::Dummy
210+
| ast::TyKind::Err(..) => break None,
211+
212+
// These end in brace, but cannot occur in a let-else statement.
213+
// They are only parsed as fields of a data structure. For the
214+
// purpose of denying trailing braces in the expression of a
215+
// let-else, we can disregard these.
216+
ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None,
217+
}
218+
}
219+
}
220+
221+
/// Returns the trailing return type in the given path, if it has one.
222+
///
223+
/// ```ignore (illustrative)
224+
/// ::std::ops::FnOnce(&str) -> fn() -> *const c_void
225+
/// ^^^^^^^^^^^^^^^^^^^^^
226+
/// ```
227+
fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
228+
let last_segment = path.segments.last()?;
229+
let args = last_segment.args.as_ref()?;
230+
match &**args {
231+
ast::GenericArgs::Parenthesized(args) => match &args.output {
232+
ast::FnRetTy::Default(_) => None,
233+
ast::FnRetTy::Ty(ret) => Some(ret),
234+
},
235+
ast::GenericArgs::AngleBracketed(_) => None,
236+
}
237+
}

compiler/rustc_hir_analysis/messages.ftl

+3-3
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,9 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
371371
.suggestion = cast the value to `{$cast_ty}`
372372
.help = cast the value to `{$cast_ty}`
373373
374-
hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end"
375-
hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types"
376-
.label = "this type is the same as the inner type without a pattern"
374+
hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end
375+
hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types
376+
.label = this type is the same as the inner type without a pattern
377377
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
378378
.label = not allowed in type signatures
379379

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
13821382
span: Span,
13831383
},
13841384
SelfTyParam(Span),
1385-
TyParam(DefId),
1385+
Param(DefId),
13861386
DefVariant,
13871387
None,
13881388
}
@@ -1498,11 +1498,11 @@ fn generics_args_err_extend<'a>(
14981498
GenericsArgsErrExtend::DefVariant => {
14991499
err.note("enum variants can't have type parameters");
15001500
}
1501-
GenericsArgsErrExtend::TyParam(def_id) => {
1502-
if let Some(span) = tcx.def_ident_span(def_id) {
1503-
let name = tcx.item_name(def_id);
1504-
err.span_note(span, format!("type parameter `{name}` defined here"));
1505-
}
1501+
GenericsArgsErrExtend::Param(def_id) => {
1502+
let span = tcx.def_ident_span(def_id).unwrap();
1503+
let kind = tcx.def_descr(def_id);
1504+
let name = tcx.item_name(def_id);
1505+
err.span_note(span, format!("{kind} `{name}` defined here"));
15061506
}
15071507
GenericsArgsErrExtend::SelfTyParam(span) => {
15081508
err.span_suggestion_verbose(

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17581758
assert_eq!(opt_self_ty, None);
17591759
let _ = self.prohibit_generic_args(
17601760
path.segments.iter(),
1761-
GenericsArgsErrExtend::TyParam(def_id),
1761+
GenericsArgsErrExtend::Param(def_id),
17621762
);
17631763
self.lower_ty_param(hir_id)
17641764
}
@@ -2191,10 +2191,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21912191

21922192
hir::ExprKind::Path(hir::QPath::Resolved(
21932193
_,
2194-
&hir::Path {
2195-
res: Res::Def(DefKind::ConstParam, def_id), ..
2194+
path @ &hir::Path {
2195+
res: Res::Def(DefKind::ConstParam, def_id),
2196+
..
21962197
},
21972198
)) => {
2199+
let _ = self.prohibit_generic_args(
2200+
path.segments.iter(),
2201+
GenericsArgsErrExtend::Param(def_id),
2202+
);
21982203
let ty = tcx
21992204
.type_of(def_id)
22002205
.no_bound_vars()

compiler/rustc_middle/src/ty/sty.rs

+39
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,45 @@ impl<'tcx> CoroutineClosureArgs<'tcx> {
401401
pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
402402
self.split().coroutine_witness_ty
403403
}
404+
405+
pub fn has_self_borrows(&self) -> bool {
406+
match self.coroutine_captures_by_ref_ty().kind() {
407+
ty::FnPtr(sig) => sig
408+
.skip_binder()
409+
.visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
410+
.is_break(),
411+
ty::Error(_) => true,
412+
_ => bug!(),
413+
}
414+
}
415+
}
416+
/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
417+
/// detect only regions bound *at* the debruijn index.
418+
struct HasRegionsBoundAt {
419+
binder: ty::DebruijnIndex,
420+
}
421+
// FIXME: Could be optimized to not walk into components with no escaping bound vars.
422+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt {
423+
type Result = ControlFlow<()>;
424+
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
425+
&mut self,
426+
t: &ty::Binder<'tcx, T>,
427+
) -> Self::Result {
428+
self.binder.shift_in(1);
429+
t.super_visit_with(self)?;
430+
self.binder.shift_out(1);
431+
ControlFlow::Continue(())
432+
}
433+
434+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
435+
if let ty::ReBound(binder, _) = *r
436+
&& self.binder == binder
437+
{
438+
ControlFlow::Break(())
439+
} else {
440+
ControlFlow::Continue(())
441+
}
442+
}
404443
}
405444

406445
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]

compiler/rustc_parse/src/parser/stmt.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use ast::Label;
1515
use rustc_ast as ast;
1616
use rustc_ast::ptr::P;
1717
use rustc_ast::token::{self, Delimiter, TokenKind};
18-
use rustc_ast::util::classify;
18+
use rustc_ast::util::classify::{self, TrailingBrace};
1919
use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
2020
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt};
2121
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
@@ -407,18 +407,24 @@ impl<'a> Parser<'a> {
407407

408408
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
409409
if let Some(trailing) = classify::expr_trailing_brace(init) {
410-
let sugg = match &trailing.kind {
411-
ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs {
412-
left: mac.args.dspan.open,
413-
right: mac.args.dspan.close,
414-
},
415-
_ => errors::WrapInParentheses::Expression {
416-
left: trailing.span.shrink_to_lo(),
417-
right: trailing.span.shrink_to_hi(),
418-
},
410+
let (span, sugg) = match trailing {
411+
TrailingBrace::MacCall(mac) => (
412+
mac.span(),
413+
errors::WrapInParentheses::MacroArgs {
414+
left: mac.args.dspan.open,
415+
right: mac.args.dspan.close,
416+
},
417+
),
418+
TrailingBrace::Expr(expr) => (
419+
expr.span,
420+
errors::WrapInParentheses::Expression {
421+
left: expr.span.shrink_to_lo(),
422+
right: expr.span.shrink_to_hi(),
423+
},
424+
),
419425
};
420426
self.dcx().emit_err(errors::InvalidCurlyInLetElse {
421-
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
427+
span: span.with_lo(span.hi() - BytePos(1)),
422428
sugg,
423429
});
424430
}

compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
300300
return Err(NoSolution);
301301
}
302302

303-
// If `Fn`/`FnMut`, we only implement this goal if we
304-
// have no captures.
305-
let no_borrows = match args.tupled_upvars_ty().kind() {
306-
ty::Tuple(tys) => tys.is_empty(),
307-
ty::Error(_) => false,
308-
_ => bug!("tuple_fields called on non-tuple"),
309-
};
310-
if closure_kind != ty::ClosureKind::FnOnce && !no_borrows {
303+
// A coroutine-closure implements `FnOnce` *always*, since it may
304+
// always be called once. It additionally implements `Fn`/`FnMut`
305+
// only if it has no upvars referencing the closure-env lifetime,
306+
// and if the closure kind permits it.
307+
if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
311308
return Err(NoSolution);
312309
}
313310

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -418,20 +418,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
418418
// Ambiguity if upvars haven't been constrained yet
419419
&& !args.tupled_upvars_ty().is_ty_var()
420420
{
421-
let no_borrows = match args.tupled_upvars_ty().kind() {
422-
ty::Tuple(tys) => tys.is_empty(),
423-
ty::Error(_) => false,
424-
_ => bug!("tuple_fields called on non-tuple"),
425-
};
426421
// A coroutine-closure implements `FnOnce` *always*, since it may
427422
// always be called once. It additionally implements `Fn`/`FnMut`
428-
// only if it has no upvars (therefore no borrows from the closure
429-
// that would need to be represented with a lifetime) and if the
430-
// closure kind permits it.
431-
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
432-
// if it takes all of its upvars by copy, and none by ref. This would
433-
// require us to record a bit more information during upvar analysis.
434-
if no_borrows && closure_kind.extends(kind) {
423+
// only if it has no upvars referencing the closure-env lifetime,
424+
// and if the closure kind permits it.
425+
if closure_kind.extends(kind) && !args.has_self_borrows() {
435426
candidates.vec.push(ClosureCandidate { is_const });
436427
} else if kind == ty::ClosureKind::FnOnce {
437428
candidates.vec.push(ClosureCandidate { is_const });

library/alloc/Cargo.toml

+12
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,15 @@ compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
4040
panic_immediate_abort = ["core/panic_immediate_abort"]
4141
# Choose algorithms that are optimized for binary size instead of runtime performance
4242
optimize_for_size = ["core/optimize_for_size"]
43+
44+
[lints.rust.unexpected_cfgs]
45+
level = "warn"
46+
# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
47+
# for rust-lang/rust. But for users of `-Zbuild-std` it does.
48+
# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
49+
check-cfg = [
50+
'cfg(bootstrap)',
51+
'cfg(no_global_oom_handling)',
52+
'cfg(no_rc)',
53+
'cfg(no_sync)',
54+
]

library/core/Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,16 @@ optimize_for_size = []
3636
# Make `RefCell` store additional debugging information, which is printed out when
3737
# a borrow error occurs
3838
debug_refcell = []
39+
40+
[lints.rust.unexpected_cfgs]
41+
level = "warn"
42+
# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
43+
# for rust-lang/rust. But for users of `-Zbuild-std` it does.
44+
# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
45+
check-cfg = [
46+
'cfg(bootstrap)',
47+
'cfg(no_fp_fmt_parse)',
48+
'cfg(stdarch_intel_sde)',
49+
# This matches `EXTRA_CHECK_CFGS` in `src/bootstrap/src/lib.rs`.
50+
'cfg(feature, values(any()))',
51+
]

0 commit comments

Comments
 (0)