Skip to content

Rollup of 8 pull requests #141040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
14662fa
docs(library/core/src/pin): fix typo "necessarily" -> "necessary"
ruancomelli Apr 13, 2025
6f23f16
docs(library/core/src/pin): rewrite for clarity
ruancomelli Apr 13, 2025
53459ff
Simplify `Vec::as_non_null` implementation and make it `const`
viliml May 5, 2025
31ebe11
normalization: avoid incompletely constraining GAT args
lcnr May 6, 2025
0185484
refactor `probe_and_consider_param_env_candidate`
lcnr May 8, 2025
df1da67
Flush errors before deep normalize in dropck_outlives
compiler-errors May 12, 2025
a508011
Expect deep norm to fail if query norm failed
compiler-errors May 12, 2025
79b2794
Remove #![feature(let_chains)] from library and src/librustdoc
est31 May 13, 2025
e1f1878
Fix set_name for vxworks. Length of name should be truncated to VX_TA…
biabbas May 14, 2025
544c8ce
Fix settimes for vxworks
biabbas May 14, 2025
ac1df15
Improve `dangerous_implicit_aurorefs` diagnostic output
Urgau May 7, 2025
9b3abe7
Use more subdiagnostics and reword the overloaded deref note
Urgau May 14, 2025
92116bc
remove `RustfmtState` to reduce `initial_rustfmt` complexity
onur-ozkan May 15, 2025
1c1a26e
Rollup merge of #139749 - ruancomelli:docs/library/core/src/pin/fix-t…
matthiaskrgr May 15, 2025
81a229e
Rollup merge of #140685 - viliml:patch-1, r=Mark-Simulacrum
matthiaskrgr May 15, 2025
bd8f39e
Rollup merge of #140712 - lcnr:normalization-gat-args, r=compiler-errors
matthiaskrgr May 15, 2025
4eb7280
Rollup merge of #140768 - Urgau:improv_autorefs-lint, r=fmease
matthiaskrgr May 15, 2025
fd9c5d2
Rollup merge of #140947 - compiler-errors:pending-norm, r=lcnr
matthiaskrgr May 15, 2025
6fff211
Rollup merge of #140966 - est31:let_chains_library, r=tgross35
matthiaskrgr May 15, 2025
0f95bbb
Rollup merge of #140990 - biabbas:vxworks, r=tgross35
matthiaskrgr May 15, 2025
da78e8d
Rollup merge of #141027 - onur-ozkan:simpler-rustfmt-initialization, …
matthiaskrgr May 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions compiler/rustc_borrowck/src/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,13 +621,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
&ocx, op, span,
) {
Ok(_) => ocx.select_all_or_error(),
Err(e) => {
if e.is_empty() {
ocx.select_all_or_error()
} else {
e
}
}
Err(e) => e,
};

// Could have no errors if a type lowering error, say, caused the query
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ lint_impl_trait_redundant_captures = all possible in-scope parameters are alread

lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dereference of a raw pointer
.note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
.raw_ptr = this raw pointer has type `{$raw_ptr_ty}`
.autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}`
.overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
.method_def = method calls to `{$method_name}` require a reference
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit

lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
Expand Down
42 changes: 29 additions & 13 deletions compiler/rustc_lint/src/autorefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDer
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;

use crate::lints::{ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsSuggestion};
use crate::lints::{
ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsMethodNote, ImplicitUnsafeAutorefsOrigin,
ImplicitUnsafeAutorefsSuggestion,
};
use crate::{LateContext, LateLintPass, LintContext};

declare_lint! {
Expand Down Expand Up @@ -92,25 +95,37 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
&& let adjustments = peel_derefs_adjustments(&**adjustments)
// 3. An automatically inserted reference (might come from a deref).
&& let [adjustment] = adjustments
&& let Some(borrow_mutbl) = has_implicit_borrow(adjustment)
&& let Some((borrow_mutbl, through_overloaded_deref)) = has_implicit_borrow(adjustment)
&& let ExprKind::Unary(UnOp::Deref, dereferenced) =
// 2. Any number of place projections.
peel_place_mappers(inner).kind
// 1. Deref of a raw pointer.
&& typeck.expr_ty(dereferenced).is_raw_ptr()
// PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
&& match expr.kind {
ExprKind::MethodCall(..) => matches!(
cx.typeck_results().type_dependent_def_id(expr.hir_id),
Some(def_id) if cx.tcx.has_attr(def_id, sym::rustc_no_implicit_autorefs)
),
_ => true,
&& let method_did = match expr.kind {
// PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
_ => None,
}
&& method_did.map(|did| cx.tcx.has_attr(did, sym::rustc_no_implicit_autorefs)).unwrap_or(true)
{
cx.emit_span_lint(
DANGEROUS_IMPLICIT_AUTOREFS,
expr.span.source_callsite(),
ImplicitUnsafeAutorefsDiag {
raw_ptr_span: dereferenced.span,
raw_ptr_ty: typeck.expr_ty(dereferenced),
origin: if through_overloaded_deref {
ImplicitUnsafeAutorefsOrigin::OverloadedDeref
} else {
ImplicitUnsafeAutorefsOrigin::Autoref {
autoref_span: inner.span,
autoref_ty: typeck.expr_ty_adjusted(inner),
}
},
method: method_did.map(|did| ImplicitUnsafeAutorefsMethodNote {
def_span: cx.tcx.def_span(did),
method_name: cx.tcx.item_name(did),
}),
suggestion: ImplicitUnsafeAutorefsSuggestion {
mutbl: borrow_mutbl.ref_prefix_str(),
deref: if is_coming_from_deref { "*" } else { "" },
Expand Down Expand Up @@ -146,11 +161,12 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen

/// Test if some adjustment has some implicit borrow.
///
/// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<Mutability> {
/// Returns `Some((mutability, was_an_overloaded_deref))` if the argument adjustment is
/// an implicit borrow (or has an implicit borrow via an overloaded deref).
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
match kind {
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some(mutbl),
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some(mutbl.into()),
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)),
Adjust::NeverToAny
| Adjust::Pointer(..)
| Adjust::ReborrowPin(..)
Expand Down
29 changes: 28 additions & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,38 @@ pub(crate) enum ShadowedIntoIterDiagSub {
#[derive(LintDiagnostic)]
#[diag(lint_implicit_unsafe_autorefs)]
#[note]
pub(crate) struct ImplicitUnsafeAutorefsDiag {
pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> {
#[label(lint_raw_ptr)]
pub raw_ptr_span: Span,
pub raw_ptr_ty: Ty<'a>,
#[subdiagnostic]
pub origin: ImplicitUnsafeAutorefsOrigin<'a>,
#[subdiagnostic]
pub method: Option<ImplicitUnsafeAutorefsMethodNote>,
#[subdiagnostic]
pub suggestion: ImplicitUnsafeAutorefsSuggestion,
}

#[derive(Subdiagnostic)]
pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> {
#[note(lint_autoref)]
Autoref {
#[primary_span]
autoref_span: Span,
autoref_ty: Ty<'a>,
},
#[note(lint_overloaded_deref)]
OverloadedDeref,
}

#[derive(Subdiagnostic)]
#[note(lint_method_def)]
pub(crate) struct ImplicitUnsafeAutorefsMethodNote {
#[primary_span]
pub def_span: Span,
pub method_name: Symbol,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
Expand Down
38 changes: 19 additions & 19 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pub(super) mod structural_traits;

use std::cell::Cell;
use std::ops::ControlFlow;

use derive_where::derive_where;
Expand Down Expand Up @@ -117,24 +118,24 @@ where
) -> Result<Candidate<I>, NoSolution> {
Self::fast_reject_assumption(ecx, goal, assumption)?;

ecx.probe(|candidate: &Result<Candidate<I>, NoSolution>| match candidate {
Ok(candidate) => inspect::ProbeKind::TraitCandidate {
source: candidate.source,
result: Ok(candidate.result),
},
Err(NoSolution) => inspect::ProbeKind::TraitCandidate {
source: CandidateSource::ParamEnv(ParamEnvSource::Global),
result: Err(NoSolution),
},
// Dealing with `ParamEnv` candidates is a bit of a mess as we need to lazily
// check whether the candidate is global while considering normalization.
//
// We need to write into `source` inside of `match_assumption`, but need to access it
// in `probe` even if the candidate does not apply before we get there. We handle this
// by using a `Cell` here. We only ever write into it inside of `match_assumption`.
let source = Cell::new(CandidateSource::ParamEnv(ParamEnvSource::Global));
ecx.probe(|result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
source: source.get(),
result: *result,
})
.enter(|ecx| {
Self::match_assumption(ecx, goal, assumption)?;
let source = ecx.characterize_param_env_assumption(goal.param_env, assumption)?;
Ok(Candidate {
source,
result: ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?,
Self::match_assumption(ecx, goal, assumption, |ecx| {
source.set(ecx.characterize_param_env_assumption(goal.param_env, assumption)?);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
})
.map(|result| Candidate { source: source.get(), result })
}

/// Try equating an assumption predicate against a goal's predicate. If it
Expand All @@ -150,10 +151,8 @@ where
) -> Result<Candidate<I>, NoSolution> {
Self::fast_reject_assumption(ecx, goal, assumption)?;

ecx.probe_trait_candidate(source).enter(|ecx| {
Self::match_assumption(ecx, goal, assumption)?;
then(ecx)
})
ecx.probe_trait_candidate(source)
.enter(|ecx| Self::match_assumption(ecx, goal, assumption, then))
}

/// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`]
Expand All @@ -169,7 +168,8 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<(), NoSolution>;
then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
) -> QueryResult<I>;

fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<(), NoSolution> {
then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
) -> QueryResult<I> {
let host_clause = assumption.as_host_effect_clause().unwrap();

let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause);
ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;

Ok(())
then(ecx)
}

/// Register additional assumptions for aliases corresponding to `~const` item bounds.
Expand Down
38 changes: 35 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,40 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<(), NoSolution> {
then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
) -> QueryResult<I> {
let cx = ecx.cx();
// FIXME(generic_associated_types): Addresses aggressive inference in #92917.
//
// If this type is a GAT with currently unconstrained arguments, we do not
// want to normalize it via a candidate which only applies for a specific
// instantiation. We could otherwise keep the GAT as rigid and succeed this way.
// See tests/ui/generic-associated-types/no-incomplete-gat-arg-inference.rs.
//
// This only avoids normalization if the GAT arguments are fully unconstrained.
// This is quite arbitrary but fixing it causes some ambiguity, see #125196.
match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
for arg in goal.predicate.alias.own_args(cx).iter() {
let Some(term) = arg.as_term() else {
continue;
};
let term = ecx.structurally_normalize_term(goal.param_env, term)?;
if term.is_infer() {
return ecx.evaluate_added_goals_and_make_canonical_response(
Certainty::AMBIGUOUS,
);
}
}
}
ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::InherentConst
| ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::UnevaluatedConst => {}
}

let projection_pred = assumption.as_projection_clause().unwrap();

let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
Expand All @@ -139,15 +172,14 @@ where

// Add GAT where clauses from the trait's definition
// FIXME: We don't need these, since these are the type's own WF obligations.
let cx = ecx.cx();
ecx.add_goals(
GoalSource::AliasWellFormed,
cx.own_predicates_of(goal.predicate.def_id())
.iter_instantiated(cx, goal.predicate.alias.args)
.map(|pred| goal.with(cx, pred)),
);

Ok(())
then(ecx)
}

fn consider_additional_alias_assumptions(
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidates
use crate::solve::inspect::ProbeKind;
use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
NoSolution, ParamEnvSource,
NoSolution, ParamEnvSource, QueryResult,
};

impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
Expand Down Expand Up @@ -150,13 +150,14 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<(), NoSolution> {
then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
) -> QueryResult<I> {
let trait_clause = assumption.as_trait_clause().unwrap();

let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;

Ok(())
then(ecx)
}

fn consider_auto_trait_candidate(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![allow(unused_crate_dependencies)]
#![cfg_attr(all(feature = "rustc", bootstrap), feature(let_chains))]
// tidy-alphabetical-end

pub mod constructor;
Expand Down
28 changes: 24 additions & 4 deletions compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,31 @@ where
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
ty
} else {
ocx.deeply_normalize(&cause, param_env, ty)?;
// Flush errors b/c `deeply_normalize` doesn't expect pending
// obligations, and we may have pending obligations from the
// branch above (from other types).
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
return Err(errors);
}

let errors = ocx.select_where_possible();
debug!("normalize errors: {ty} ~> {errors:#?}");
return Err(errors);
// When query normalization fails, we don't get back an interesting
// reason that we could use to report an error in borrowck. In order to turn
// this into a reportable error, we deeply normalize again. We don't expect
// this to succeed, so delay a bug if it does.
match ocx.deeply_normalize(&cause, param_env, ty) {
Ok(_) => {
tcx.dcx().span_delayed_bug(
span,
format!(
"query normalize succeeded of {ty}, \
but deep normalize failed",
),
);
ty
}
Err(errors) => return Err(errors),
}
};

match ty.kind() {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1760,12 +1760,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

if is_match {
let generics = self.tcx().generics_of(obligation.predicate.def_id);
// FIXME(generic-associated-types): Addresses aggressive inference in #92917.
// FIXME(generic_associated_types): Addresses aggressive inference in #92917.
// If this type is a GAT, and of the GAT args resolve to something new,
// that means that we must have newly inferred something about the GAT.
// We should give up in that case.
// FIXME(generic-associated-types): This only detects one layer of inference,
// which is probably not what we actually want, but fixing it causes some ambiguity:
//
// This only detects one layer of inference, which is probably not what we actually
// want, but fixing it causes some ambiguity:
// <https://github.com/rust-lang/rust/issues/125196>.
if !generics.is_own_empty()
&& obligation.predicate.args[generics.parent_count..].iter().any(|&p| {
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_type_ir/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,14 @@ pub trait GenericArg<I: Interner<GenericArg = Self>>:
+ From<I::Region>
+ From<I::Const>
{
fn as_term(&self) -> Option<I::Term> {
match self.kind() {
ty::GenericArgKind::Lifetime(_) => None,
ty::GenericArgKind::Type(ty) => Some(ty.into()),
ty::GenericArgKind::Const(ct) => Some(ct.into()),
}
}

fn as_type(&self) -> Option<I::Ty> {
if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
}
Expand Down
Loading
Loading