Skip to content

Commit

Permalink
Auto merge of rust-lang#133234 - jhpratt:rollup-42dmg4p, r=jhpratt
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Nov 20, 2024
2 parents 70e814b + b9cd5eb commit fda6892
Show file tree
Hide file tree
Showing 29 changed files with 305 additions and 159 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
let mut cmd = Command::new(&pager_name);
// FIXME: find if other pagers accept color options
let mut print_formatted = if pager_name == "less" {
cmd.arg("-r");
cmd.arg("-R");
true
} else {
["bat", "catbat", "delta"].iter().any(|v| *v == pager_name)
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
"lang items are subject to change",
),
rustc_attr!(
rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
EncodeCrossCrate::Yes,
"#[rustc_as_ptr] is used to mark functions returning pointers to their inner allocations."
),
rustc_attr!(
rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
EncodeCrossCrate::Yes,
Expand Down
27 changes: 13 additions & 14 deletions compiler/rustc_lint/src/dangling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,10 @@ declare_lint! {
}

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

fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::MethodCall(method, receiver, _args, _span) = expr.kind
&& matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& cx.tcx.has_attr(fn_id, sym::rustc_as_ptr)
&& is_temporary_rvalue(receiver)
&& let ty = cx.typeck_results().expr_ty(receiver)
&& is_interesting(cx.tcx, ty)
&& owns_allocation(cx.tcx, ty)
{
// FIXME: use `emit_node_lint` when `#[primary_span]` is added.
cx.tcx.emit_node_span_lint(
Expand Down Expand Up @@ -199,24 +197,25 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
}
}

// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>,
// or any of the above in arbitrary many nested Box'es.
fn is_interesting(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>, UnsafeCell,
// SyncUnsafeCell, or any of the above in arbitrary many nested Box'es.
fn owns_allocation(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
if ty.is_array() {
true
} else if let Some(inner) = ty.boxed_ty() {
inner.is_slice()
|| inner.is_str()
|| inner.ty_adt_def().is_some_and(|def| tcx.is_lang_item(def.did(), LangItem::CStr))
|| is_interesting(tcx, inner)
|| owns_allocation(tcx, inner)
} else if let Some(def) = ty.ty_adt_def() {
for lang_item in [LangItem::String, LangItem::MaybeUninit] {
for lang_item in [LangItem::String, LangItem::MaybeUninit, LangItem::UnsafeCell] {
if tcx.is_lang_item(def.did(), lang_item) {
return true;
}
}
tcx.get_diagnostic_name(def.did())
.is_some_and(|name| matches!(name, sym::cstring_type | sym::Vec | sym::Cell))
tcx.get_diagnostic_name(def.did()).is_some_and(|name| {
matches!(name, sym::cstring_type | sym::Vec | sym::Cell | sym::SyncUnsafeCell)
})
} else {
false
}
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,19 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
let dont_need_to_run: FxIndexSet<LintId> = store
.get_lints()
.into_iter()
.filter(|lint| {
// Lints that show up in future-compat reports must always be run.
let has_future_breakage =
lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
!has_future_breakage && !lint.eval_always
})
.filter_map(|lint| {
if !lint.eval_always {
let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
if matches!(lint_level, (Level::Allow, ..))
|| (matches!(lint_level, (.., LintLevelSource::Default)))
&& lint.default_level(tcx.sess.edition()) == Level::Allow
{
Some(LintId::of(lint))
} else {
None
}
let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
if matches!(lint_level, (Level::Allow, ..))
|| (matches!(lint_level, (.., LintLevelSource::Default)))
&& lint.default_level(tcx.sess.edition()) == Level::Allow
{
Some(LintId::of(lint))
} else {
None
}
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,20 @@ impl FutureIncompatibilityReason {
| FutureIncompatibilityReason::Custom(_) => None,
}
}

pub fn has_future_breakage(self) -> bool {
match self {
FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => true,

FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
| FutureIncompatibilityReason::FutureReleaseSemanticsChange
| FutureIncompatibilityReason::EditionError(_)
| FutureIncompatibilityReason::EditionSemanticsChange(_)
| FutureIncompatibilityReason::EditionAndFutureReleaseError(_)
| FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(_)
| FutureIncompatibilityReason::Custom(_) => false,
}
}
}

impl FutureIncompatibleInfo {
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,7 @@ pub fn lint_level(
let has_future_breakage = future_incompatible.map_or(
// Default allow lints trigger too often for testing.
sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow,
|incompat| {
matches!(
incompat.reason,
FutureIncompatibilityReason::FutureReleaseErrorReportInDeps
)
},
|incompat| incompat.reason.has_future_breakage(),
);

// Convert lint level to error level.
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied())
}

fn is_const_impl(self, def_id: DefId) -> bool {
fn impl_is_const(self, def_id: DefId) -> bool {
self.is_conditionally_const(def_id)
}

fn fn_is_const(self, def_id: DefId) -> bool {
self.is_conditionally_const(def_id)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,76 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
)
}

/// This duplicates `extract_tupled_inputs_and_output_from_callable` but needs
/// to return different information (namely, the def id and args) so that we can
/// create const conditions.
///
/// Doing so on all calls to `extract_tupled_inputs_and_output_from_callable`
/// would be wasteful.
pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
cx: I,
self_ty: I::Ty,
) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
match self_ty.kind() {
ty::FnDef(def_id, args) => {
let sig = cx.fn_sig(def_id);
if sig.skip_binder().is_fn_trait_compatible()
&& !cx.has_target_features(def_id)
&& cx.fn_is_const(def_id)
{
Ok((
sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
def_id,
args,
))
} else {
return Err(NoSolution);
}
}
// `FnPtr`s are not const for now.
ty::FnPtr(..) => {
return Err(NoSolution);
}
// `Closure`s are not const for now.
ty::Closure(..) => {
return Err(NoSolution);
}
// `CoroutineClosure`s are not const for now.
ty::CoroutineClosure(..) => {
return Err(NoSolution);
}

ty::Bool
| ty::Char
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Adt(_, _)
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Slice(_)
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::Dynamic(_, _, _)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Pat(_, _)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Placeholder(..)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Error(_) => return Err(NoSolution),

ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
panic!("unexpected type `{self_ty:?}`")
}
}
}

/// Assemble a list of predicates that would be present on a theoretical
/// user impl for an object type. These predicates must be checked any time
/// we assemble a built-in object candidate for an object type, since they
Expand Down
55 changes: 46 additions & 9 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, elaborate};
use tracing::instrument;

use super::assembly::Candidate;
use super::assembly::{Candidate, structural_traits};
use crate::delegate::SolverDelegate;
use crate::solve::assembly::{self};
use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution,
QueryResult,
QueryResult, assembly,
};

impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
Expand Down Expand Up @@ -142,7 +142,7 @@ where
ty::ImplPolarity::Positive => {}
};

if !cx.is_const_impl(impl_def_id) {
if !cx.impl_is_const(impl_def_id) {
return Err(NoSolution);
}

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

fn consider_builtin_pointer_like_candidate(
Expand All @@ -225,11 +225,48 @@ where
}

fn consider_builtin_fn_trait_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
_kind: rustc_type_ir::ClosureKind,
) -> Result<Candidate<I>, NoSolution> {
todo!("Fn* are not yet const")
let cx = ecx.cx();

let self_ty = goal.predicate.self_ty();
let (inputs_and_output, def_id, args) =
structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;

// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = inputs_and_output.map_bound(|(_, output)| {
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
});
let requirements = cx
.const_conditions(def_id)
.iter_instantiated(cx, args)
.map(|trait_ref| {
(
GoalSource::ImplWhereBound,
goal.with(cx, trait_ref.to_host_effect_clause(cx, goal.predicate.constness)),
)
})
.chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);

let pred = inputs_and_output
.map_bound(|(inputs, _)| {
ty::TraitRef::new(cx, goal.predicate.def_id(), [
goal.predicate.self_ty(),
Ty::new_tup(cx, inputs.as_slice()),
])
})
.to_host_effect_clause(cx, goal.predicate.constness);

Self::probe_and_consider_implied_clause(
ecx,
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
pred,
requirements,
)
}

fn consider_builtin_async_fn_trait_candidates(
Expand Down Expand Up @@ -314,7 +351,7 @@ where
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Destruct is not const")
Err(NoSolution)
}

fn consider_builtin_transmute_candidate(
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ where
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
}
};

// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
});
Expand All @@ -408,8 +411,6 @@ where
})
.upcast(cx);

// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
Self::probe_and_consider_implied_clause(
ecx,
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
Expand Down Expand Up @@ -438,6 +439,9 @@ where
goal_kind,
env_region,
)?;

// A built-in `AsyncFn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
|AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty])
Expand Down Expand Up @@ -494,8 +498,6 @@ where
)
.upcast(cx);

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

0 comments on commit fda6892

Please sign in to comment.