Skip to content

Commit fda6892

Browse files
committed
Auto merge of rust-lang#133234 - jhpratt:rollup-42dmg4p, r=jhpratt
Rollup of 5 pull requests Successful merges: - rust-lang#132732 (Use attributes for `dangling_pointers_from_temporaries` lint) - rust-lang#133108 (lints_that_dont_need_to_run: never skip future-compat-reported lints) - rust-lang#133190 (CI: use free runner in dist-aarch64-msvc) - rust-lang#133196 (Make rustc --explain compatible with BusyBox less) - rust-lang#133216 (Implement `~const Fn` trait goal in the new solver) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 70e814b + b9cd5eb commit fda6892

File tree

29 files changed

+305
-159
lines changed

29 files changed

+305
-159
lines changed

compiler/rustc_driver_impl/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
577577
let mut cmd = Command::new(&pager_name);
578578
// FIXME: find if other pagers accept color options
579579
let mut print_formatted = if pager_name == "less" {
580-
cmd.arg("-r");
580+
cmd.arg("-R");
581581
true
582582
} else {
583583
["bat", "catbat", "delta"].iter().any(|v| *v == pager_name)

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
879879
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
880880
"lang items are subject to change",
881881
),
882+
rustc_attr!(
883+
rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
884+
EncodeCrossCrate::Yes,
885+
"#[rustc_as_ptr] is used to mark functions returning pointers to their inner allocations."
886+
),
882887
rustc_attr!(
883888
rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
884889
EncodeCrossCrate::Yes,

compiler/rustc_lint/src/dangling.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,10 @@ declare_lint! {
4343
}
4444

4545
/// FIXME: false negatives (i.e. the lint is not emitted when it should be)
46-
/// 1. Method calls that are not checked for:
47-
/// - [`temporary_unsafe_cell.get()`][`core::cell::UnsafeCell::get()`]
48-
/// - [`temporary_sync_unsafe_cell.get()`][`core::cell::SyncUnsafeCell::get()`]
49-
/// 2. Ways to get a temporary that are not recognized:
46+
/// 1. Ways to get a temporary that are not recognized:
5047
/// - `owning_temporary.field`
5148
/// - `owning_temporary[index]`
52-
/// 3. No checks for ref-to-ptr conversions:
49+
/// 2. No checks for ref-to-ptr conversions:
5350
/// - `&raw [mut] temporary`
5451
/// - `&temporary as *(const|mut) _`
5552
/// - `ptr::from_ref(&temporary)` and friends
@@ -133,10 +130,11 @@ impl DanglingPointerSearcher<'_, '_> {
133130

134131
fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
135132
if let ExprKind::MethodCall(method, receiver, _args, _span) = expr.kind
136-
&& matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
133+
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
134+
&& cx.tcx.has_attr(fn_id, sym::rustc_as_ptr)
137135
&& is_temporary_rvalue(receiver)
138136
&& let ty = cx.typeck_results().expr_ty(receiver)
139-
&& is_interesting(cx.tcx, ty)
137+
&& owns_allocation(cx.tcx, ty)
140138
{
141139
// FIXME: use `emit_node_lint` when `#[primary_span]` is added.
142140
cx.tcx.emit_node_span_lint(
@@ -199,24 +197,25 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
199197
}
200198
}
201199

202-
// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>,
203-
// or any of the above in arbitrary many nested Box'es.
204-
fn is_interesting(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
200+
// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>, UnsafeCell,
201+
// SyncUnsafeCell, or any of the above in arbitrary many nested Box'es.
202+
fn owns_allocation(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
205203
if ty.is_array() {
206204
true
207205
} else if let Some(inner) = ty.boxed_ty() {
208206
inner.is_slice()
209207
|| inner.is_str()
210208
|| inner.ty_adt_def().is_some_and(|def| tcx.is_lang_item(def.did(), LangItem::CStr))
211-
|| is_interesting(tcx, inner)
209+
|| owns_allocation(tcx, inner)
212210
} else if let Some(def) = ty.ty_adt_def() {
213-
for lang_item in [LangItem::String, LangItem::MaybeUninit] {
211+
for lang_item in [LangItem::String, LangItem::MaybeUninit, LangItem::UnsafeCell] {
214212
if tcx.is_lang_item(def.did(), lang_item) {
215213
return true;
216214
}
217215
}
218-
tcx.get_diagnostic_name(def.did())
219-
.is_some_and(|name| matches!(name, sym::cstring_type | sym::Vec | sym::Cell))
216+
tcx.get_diagnostic_name(def.did()).is_some_and(|name| {
217+
matches!(name, sym::cstring_type | sym::Vec | sym::Cell | sym::SyncUnsafeCell)
218+
})
220219
} else {
221220
false
222221
}

compiler/rustc_lint/src/levels.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,19 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
123123
let dont_need_to_run: FxIndexSet<LintId> = store
124124
.get_lints()
125125
.into_iter()
126+
.filter(|lint| {
127+
// Lints that show up in future-compat reports must always be run.
128+
let has_future_breakage =
129+
lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
130+
!has_future_breakage && !lint.eval_always
131+
})
126132
.filter_map(|lint| {
127-
if !lint.eval_always {
128-
let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
129-
if matches!(lint_level, (Level::Allow, ..))
130-
|| (matches!(lint_level, (.., LintLevelSource::Default)))
131-
&& lint.default_level(tcx.sess.edition()) == Level::Allow
132-
{
133-
Some(LintId::of(lint))
134-
} else {
135-
None
136-
}
133+
let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
134+
if matches!(lint_level, (Level::Allow, ..))
135+
|| (matches!(lint_level, (.., LintLevelSource::Default)))
136+
&& lint.default_level(tcx.sess.edition()) == Level::Allow
137+
{
138+
Some(LintId::of(lint))
137139
} else {
138140
None
139141
}

compiler/rustc_lint_defs/src/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,20 @@ impl FutureIncompatibilityReason {
466466
| FutureIncompatibilityReason::Custom(_) => None,
467467
}
468468
}
469+
470+
pub fn has_future_breakage(self) -> bool {
471+
match self {
472+
FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => true,
473+
474+
FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
475+
| FutureIncompatibilityReason::FutureReleaseSemanticsChange
476+
| FutureIncompatibilityReason::EditionError(_)
477+
| FutureIncompatibilityReason::EditionSemanticsChange(_)
478+
| FutureIncompatibilityReason::EditionAndFutureReleaseError(_)
479+
| FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(_)
480+
| FutureIncompatibilityReason::Custom(_) => false,
481+
}
482+
}
469483
}
470484

471485
impl FutureIncompatibleInfo {

compiler/rustc_middle/src/lint.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,7 @@ pub fn lint_level(
290290
let has_future_breakage = future_incompatible.map_or(
291291
// Default allow lints trigger too often for testing.
292292
sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow,
293-
|incompat| {
294-
matches!(
295-
incompat.reason,
296-
FutureIncompatibilityReason::FutureReleaseErrorReportInDeps
297-
)
298-
},
293+
|incompat| incompat.reason.has_future_breakage(),
299294
);
300295

301296
// Convert lint level to error level.

compiler/rustc_middle/src/ty/context.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
376376
self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied())
377377
}
378378

379-
fn is_const_impl(self, def_id: DefId) -> bool {
379+
fn impl_is_const(self, def_id: DefId) -> bool {
380+
self.is_conditionally_const(def_id)
381+
}
382+
383+
fn fn_is_const(self, def_id: DefId) -> bool {
380384
self.is_conditionally_const(def_id)
381385
}
382386

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

+70
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,76 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
633633
)
634634
}
635635

636+
/// This duplicates `extract_tupled_inputs_and_output_from_callable` but needs
637+
/// to return different information (namely, the def id and args) so that we can
638+
/// create const conditions.
639+
///
640+
/// Doing so on all calls to `extract_tupled_inputs_and_output_from_callable`
641+
/// would be wasteful.
642+
pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
643+
cx: I,
644+
self_ty: I::Ty,
645+
) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
646+
match self_ty.kind() {
647+
ty::FnDef(def_id, args) => {
648+
let sig = cx.fn_sig(def_id);
649+
if sig.skip_binder().is_fn_trait_compatible()
650+
&& !cx.has_target_features(def_id)
651+
&& cx.fn_is_const(def_id)
652+
{
653+
Ok((
654+
sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
655+
def_id,
656+
args,
657+
))
658+
} else {
659+
return Err(NoSolution);
660+
}
661+
}
662+
// `FnPtr`s are not const for now.
663+
ty::FnPtr(..) => {
664+
return Err(NoSolution);
665+
}
666+
// `Closure`s are not const for now.
667+
ty::Closure(..) => {
668+
return Err(NoSolution);
669+
}
670+
// `CoroutineClosure`s are not const for now.
671+
ty::CoroutineClosure(..) => {
672+
return Err(NoSolution);
673+
}
674+
675+
ty::Bool
676+
| ty::Char
677+
| ty::Int(_)
678+
| ty::Uint(_)
679+
| ty::Float(_)
680+
| ty::Adt(_, _)
681+
| ty::Foreign(_)
682+
| ty::Str
683+
| ty::Array(_, _)
684+
| ty::Slice(_)
685+
| ty::RawPtr(_, _)
686+
| ty::Ref(_, _, _)
687+
| ty::Dynamic(_, _, _)
688+
| ty::Coroutine(_, _)
689+
| ty::CoroutineWitness(..)
690+
| ty::Never
691+
| ty::Tuple(_)
692+
| ty::Pat(_, _)
693+
| ty::Alias(_, _)
694+
| ty::Param(_)
695+
| ty::Placeholder(..)
696+
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
697+
| ty::Error(_) => return Err(NoSolution),
698+
699+
ty::Bound(..)
700+
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
701+
panic!("unexpected type `{self_ty:?}`")
702+
}
703+
}
704+
}
705+
636706
/// Assemble a list of predicates that would be present on a theoretical
637707
/// user impl for an object type. These predicates must be checked any time
638708
/// we assemble a built-in object candidate for an object type, since they

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

+46-9
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
44
use rustc_type_ir::fast_reject::DeepRejectCtxt;
55
use rustc_type_ir::inherent::*;
6+
use rustc_type_ir::lang_items::TraitSolverLangItem;
67
use rustc_type_ir::{self as ty, Interner, elaborate};
78
use tracing::instrument;
89

9-
use super::assembly::Candidate;
10+
use super::assembly::{Candidate, structural_traits};
1011
use crate::delegate::SolverDelegate;
11-
use crate::solve::assembly::{self};
1212
use crate::solve::{
1313
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution,
14-
QueryResult,
14+
QueryResult, assembly,
1515
};
1616

1717
impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
@@ -142,7 +142,7 @@ where
142142
ty::ImplPolarity::Positive => {}
143143
};
144144

145-
if !cx.is_const_impl(impl_def_id) {
145+
if !cx.impl_is_const(impl_def_id) {
146146
return Err(NoSolution);
147147
}
148148

@@ -207,7 +207,7 @@ where
207207
_ecx: &mut EvalCtxt<'_, D>,
208208
_goal: Goal<I, Self>,
209209
) -> Result<Candidate<I>, NoSolution> {
210-
todo!("Copy/Clone is not yet const")
210+
Err(NoSolution)
211211
}
212212

213213
fn consider_builtin_pointer_like_candidate(
@@ -225,11 +225,48 @@ where
225225
}
226226

227227
fn consider_builtin_fn_trait_candidates(
228-
_ecx: &mut EvalCtxt<'_, D>,
229-
_goal: Goal<I, Self>,
228+
ecx: &mut EvalCtxt<'_, D>,
229+
goal: Goal<I, Self>,
230230
_kind: rustc_type_ir::ClosureKind,
231231
) -> Result<Candidate<I>, NoSolution> {
232-
todo!("Fn* are not yet const")
232+
let cx = ecx.cx();
233+
234+
let self_ty = goal.predicate.self_ty();
235+
let (inputs_and_output, def_id, args) =
236+
structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
237+
238+
// A built-in `Fn` impl only holds if the output is sized.
239+
// (FIXME: technically we only need to check this if the type is a fn ptr...)
240+
let output_is_sized_pred = inputs_and_output.map_bound(|(_, output)| {
241+
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
242+
});
243+
let requirements = cx
244+
.const_conditions(def_id)
245+
.iter_instantiated(cx, args)
246+
.map(|trait_ref| {
247+
(
248+
GoalSource::ImplWhereBound,
249+
goal.with(cx, trait_ref.to_host_effect_clause(cx, goal.predicate.constness)),
250+
)
251+
})
252+
.chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);
253+
254+
let pred = inputs_and_output
255+
.map_bound(|(inputs, _)| {
256+
ty::TraitRef::new(cx, goal.predicate.def_id(), [
257+
goal.predicate.self_ty(),
258+
Ty::new_tup(cx, inputs.as_slice()),
259+
])
260+
})
261+
.to_host_effect_clause(cx, goal.predicate.constness);
262+
263+
Self::probe_and_consider_implied_clause(
264+
ecx,
265+
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
266+
goal,
267+
pred,
268+
requirements,
269+
)
233270
}
234271

235272
fn consider_builtin_async_fn_trait_candidates(
@@ -314,7 +351,7 @@ where
314351
_ecx: &mut EvalCtxt<'_, D>,
315352
_goal: Goal<I, Self>,
316353
) -> Result<Candidate<I>, NoSolution> {
317-
unreachable!("Destruct is not const")
354+
Err(NoSolution)
318355
}
319356

320357
fn consider_builtin_transmute_candidate(

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ where
394394
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
395395
}
396396
};
397+
398+
// A built-in `Fn` impl only holds if the output is sized.
399+
// (FIXME: technically we only need to check this if the type is a fn ptr...)
397400
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
398401
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
399402
});
@@ -408,8 +411,6 @@ where
408411
})
409412
.upcast(cx);
410413

411-
// A built-in `Fn` impl only holds if the output is sized.
412-
// (FIXME: technically we only need to check this if the type is a fn ptr...)
413414
Self::probe_and_consider_implied_clause(
414415
ecx,
415416
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
@@ -438,6 +439,9 @@ where
438439
goal_kind,
439440
env_region,
440441
)?;
442+
443+
// A built-in `AsyncFn` impl only holds if the output is sized.
444+
// (FIXME: technically we only need to check this if the type is a fn ptr...)
441445
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
442446
|AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
443447
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty])
@@ -494,8 +498,6 @@ where
494498
)
495499
.upcast(cx);
496500

497-
// A built-in `AsyncFn` impl only holds if the output is sized.
498-
// (FIXME: technically we only need to check this if the type is a fn ptr...)
499501
Self::probe_and_consider_implied_clause(
500502
ecx,
501503
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),

0 commit comments

Comments
 (0)