Skip to content

Commit 00ded39

Browse files
committed
Auto merge of #135519 - workingjubilee:rollup-xq9yryh, r=workingjubilee
Rollup of 11 pull requests Successful merges: - #134913 (bootstrap: do not rely on LIBRARY_PATH env variable) - #134940 (Make sure to scrape region constraints from deeply normalizing type outlives assumptions in borrowck) - #135228 (Improve `DispatchFromDyn` and `CoerceUnsized` impl validation) - #135264 (Consider more erroneous layouts as `LayoutError::ReferencesError` to suppress spurious errors) - #135302 (for purely return-type based searches, deprioritize clone-like functions) - #135353 (re-add --disable-minification to rustdoc) - #135380 (Make sure we can produce `ConstArgHasWrongType` errors for valtree consts) - #135423 (Enforce syntactical stability of const traits in HIR) - #135425 (Do not consider traits that have unsatisfied const conditions to be conditionally const) - #135499 (fix underlining of hovered intra-doc links.) - #135505 (Fix clippy lints in rustdoc) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 93ba568 + 4f25a31 commit 00ded39

File tree

59 files changed

+871
-162
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+871
-162
lines changed

Diff for: compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+48-19
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ use rustc_infer::infer::canonical::QueryRegionConstraints;
55
use rustc_infer::infer::outlives::env::RegionBoundPairs;
66
use rustc_infer::infer::region_constraints::GenericKind;
77
use rustc_infer::infer::{InferCtxt, outlives};
8+
use rustc_infer::traits::ScrubbedTraitError;
89
use rustc_middle::mir::ConstraintCategory;
910
use rustc_middle::traits::ObligationCause;
1011
use rustc_middle::traits::query::OutlivesBound;
1112
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
1213
use rustc_span::{ErrorGuaranteed, Span};
13-
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
14-
use rustc_trait_selection::solve::deeply_normalize;
14+
use rustc_trait_selection::solve::NoSolution;
15+
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1516
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
1617
use tracing::{debug, instrument};
1718
use type_op::TypeOpOutput;
@@ -229,24 +230,14 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
229230
let mut constraints = vec![];
230231
let mut known_type_outlives_obligations = vec![];
231232
for bound in param_env.caller_bounds() {
232-
let Some(mut outlives) = bound.as_type_outlives_clause() else { continue };
233-
234-
// In the new solver, normalize the type-outlives obligation assumptions.
235-
if self.infcx.next_trait_solver() {
236-
match deeply_normalize(
237-
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), param_env),
233+
if let Some(outlives) = bound.as_type_outlives_clause() {
234+
self.normalize_and_push_type_outlives_obligation(
238235
outlives,
239-
) {
240-
Ok(normalized_outlives) => {
241-
outlives = normalized_outlives;
242-
}
243-
Err(e) => {
244-
self.infcx.err_ctxt().report_fulfillment_errors(e);
245-
}
246-
}
247-
}
248-
249-
known_type_outlives_obligations.push(outlives);
236+
span,
237+
&mut known_type_outlives_obligations,
238+
&mut constraints,
239+
);
240+
};
250241
}
251242

252243
let unnormalized_input_output_tys = self
@@ -356,6 +347,44 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
356347
}
357348
}
358349

350+
fn normalize_and_push_type_outlives_obligation(
351+
&self,
352+
mut outlives: ty::PolyTypeOutlivesPredicate<'tcx>,
353+
span: Span,
354+
known_type_outlives_obligations: &mut Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
355+
constraints: &mut Vec<&QueryRegionConstraints<'tcx>>,
356+
) {
357+
// In the new solver, normalize the type-outlives obligation assumptions.
358+
if self.infcx.next_trait_solver() {
359+
let Ok(TypeOpOutput {
360+
output: normalized_outlives,
361+
constraints: constraints_normalize,
362+
error_info: _,
363+
}) = CustomTypeOp::new(
364+
|ocx| {
365+
ocx.deeply_normalize(
366+
&ObligationCause::dummy_with_span(span),
367+
self.param_env,
368+
outlives,
369+
)
370+
.map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
371+
},
372+
"normalize type outlives obligation",
373+
)
374+
.fully_perform(self.infcx, span)
375+
else {
376+
self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}"));
377+
return;
378+
};
379+
outlives = normalized_outlives;
380+
if let Some(c) = constraints_normalize {
381+
constraints.push(c);
382+
}
383+
}
384+
385+
known_type_outlives_obligations.push(outlives);
386+
}
387+
359388
/// Update the type of a single local, which should represent
360389
/// either the return type of the MIR or one of its arguments. At
361390
/// the same time, compute and add any implied bounds that come

Diff for: compiler/rustc_const_eval/src/check_consts/check.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ use crate::errors;
3535
type QualifResults<'mir, 'tcx, Q> =
3636
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
3737

38+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
39+
enum ConstConditionsHold {
40+
Yes,
41+
No,
42+
}
43+
3844
#[derive(Default)]
3945
pub(crate) struct Qualifs<'mir, 'tcx> {
4046
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
@@ -376,15 +382,15 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
376382
callee: DefId,
377383
callee_args: ty::GenericArgsRef<'tcx>,
378384
call_span: Span,
379-
) -> bool {
385+
) -> Option<ConstConditionsHold> {
380386
let tcx = self.tcx;
381387
if !tcx.is_conditionally_const(callee) {
382-
return false;
388+
return None;
383389
}
384390

385391
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
386392
if const_conditions.is_empty() {
387-
return false;
393+
return None;
388394
}
389395

390396
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
@@ -413,12 +419,13 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
413419
}));
414420

415421
let errors = ocx.select_all_or_error();
416-
if !errors.is_empty() {
422+
if errors.is_empty() {
423+
Some(ConstConditionsHold::Yes)
424+
} else {
417425
tcx.dcx()
418426
.span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
427+
Some(ConstConditionsHold::No)
419428
}
420-
421-
true
422429
}
423430

424431
pub fn check_drop_terminator(
@@ -706,7 +713,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
706713
trace!("attempting to call a trait method");
707714
let trait_is_const = tcx.is_const_trait(trait_did);
708715

709-
if trait_is_const {
716+
// Only consider a trait to be const if the const conditions hold.
717+
// Otherwise, it's really misleading to call something "conditionally"
718+
// const when it's very obviously not conditionally const.
719+
if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
710720
// Trait calls are always conditionally-const.
711721
self.check_op(ops::ConditionallyConstCall {
712722
callee,
@@ -730,7 +740,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
730740
}
731741

732742
// Even if we know the callee, ensure we can use conditionally-const calls.
733-
if has_const_conditions {
743+
if has_const_conditions.is_some() {
734744
self.check_op(ops::ConditionallyConstCall {
735745
callee,
736746
args: fn_args,

Diff for: compiler/rustc_hir_analysis/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait
135135
136136
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
137137
138-
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
138+
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else
139139
.note = extra field `{$name}` of type `{$ty}` is not allowed
140140
141141
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported

Diff for: compiler/rustc_hir_analysis/src/coherence/builtin.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -259,19 +259,37 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
259259
let coerced_fields = fields
260260
.iter()
261261
.filter(|field| {
262+
// Ignore PhantomData fields
263+
let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
264+
if tcx
265+
.try_normalize_erasing_regions(
266+
ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
267+
unnormalized_ty,
268+
)
269+
.unwrap_or(unnormalized_ty)
270+
.is_phantom_data()
271+
{
272+
return false;
273+
}
274+
262275
let ty_a = field.ty(tcx, args_a);
263276
let ty_b = field.ty(tcx, args_b);
264277

265-
if let Ok(layout) =
266-
tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
267-
{
268-
if layout.is_1zst() {
278+
// FIXME: We could do normalization here, but is it really worth it?
279+
if ty_a == ty_b {
280+
// Allow 1-ZSTs that don't mention type params.
281+
//
282+
// Allowing type params here would allow us to possibly transmute
283+
// between ZSTs, which may be used to create library unsoundness.
284+
if let Ok(layout) =
285+
tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
286+
&& layout.is_1zst()
287+
&& !ty_a.has_non_region_param()
288+
{
269289
// ignore 1-ZST fields
270290
return false;
271291
}
272-
}
273292

274-
if ty_a == ty_b {
275293
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
276294
span,
277295
name: field.name,
@@ -460,8 +478,16 @@ pub(crate) fn coerce_unsized_info<'tcx>(
460478
.filter_map(|(i, f)| {
461479
let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
462480

463-
if tcx.type_of(f.did).instantiate_identity().is_phantom_data() {
464-
// Ignore PhantomData fields
481+
// Ignore PhantomData fields
482+
let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
483+
if tcx
484+
.try_normalize_erasing_regions(
485+
ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
486+
unnormalized_ty,
487+
)
488+
.unwrap_or(unnormalized_ty)
489+
.is_phantom_data()
490+
{
465491
return None;
466492
}
467493

Diff for: compiler/rustc_middle/src/middle/stability.rs

+87-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ pub enum StabilityLevel {
3030
Stable,
3131
}
3232

33+
#[derive(Copy, Clone)]
34+
pub enum UnstableKind {
35+
/// Enforcing regular stability of an item
36+
Regular,
37+
/// Enforcing const stability of an item
38+
Const(Span),
39+
}
40+
3341
/// An entry in the `depr_map`.
3442
#[derive(Copy, Clone, HashStable, Debug, Encodable, Decodable)]
3543
pub struct DeprecationEntry {
@@ -108,10 +116,16 @@ pub fn report_unstable(
108116
is_soft: bool,
109117
span: Span,
110118
soft_handler: impl FnOnce(&'static Lint, Span, String),
119+
kind: UnstableKind,
111120
) {
121+
let qual = match kind {
122+
UnstableKind::Regular => "",
123+
UnstableKind::Const(_) => " const",
124+
};
125+
112126
let msg = match reason {
113-
Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
114-
None => format!("use of unstable library feature `{feature}`"),
127+
Some(r) => format!("use of unstable{qual} library feature `{feature}`: {r}"),
128+
None => format!("use of unstable{qual} library feature `{feature}`"),
115129
};
116130

117131
if is_soft {
@@ -121,6 +135,9 @@ pub fn report_unstable(
121135
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
122136
err.span_suggestion(inner_types, msg, sugg, applicability);
123137
}
138+
if let UnstableKind::Const(kw) = kind {
139+
err.span_label(kw, "trait is not stable as const yet");
140+
}
124141
err.emit();
125142
}
126143
}
@@ -587,13 +604,81 @@ impl<'tcx> TyCtxt<'tcx> {
587604
is_soft,
588605
span,
589606
soft_handler,
607+
UnstableKind::Regular,
590608
),
591609
EvalResult::Unmarked => unmarked(span, def_id),
592610
}
593611

594612
is_allowed
595613
}
596614

615+
/// This function is analogous to `check_optional_stability` but with the logic in
616+
/// `eval_stability_allow_unstable` inlined, and which operating on const stability
617+
/// instead of regular stability.
618+
///
619+
/// This enforces *syntactical* const stability of const traits. In other words,
620+
/// it enforces the ability to name `~const`/`const` traits in trait bounds in various
621+
/// syntax positions in HIR (including in the trait of an impl header).
622+
pub fn check_const_stability(self, def_id: DefId, span: Span, const_kw_span: Span) {
623+
let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
624+
if !is_staged_api {
625+
return;
626+
}
627+
628+
// Only the cross-crate scenario matters when checking unstable APIs
629+
let cross_crate = !def_id.is_local();
630+
if !cross_crate {
631+
return;
632+
}
633+
634+
let stability = self.lookup_const_stability(def_id);
635+
debug!(
636+
"stability: \
637+
inspecting def_id={:?} span={:?} of stability={:?}",
638+
def_id, span, stability
639+
);
640+
641+
match stability {
642+
Some(ConstStability {
643+
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
644+
feature,
645+
..
646+
}) => {
647+
assert!(!is_soft);
648+
649+
if span.allows_unstable(feature) {
650+
debug!("body stability: skipping span={:?} since it is internal", span);
651+
return;
652+
}
653+
if self.features().enabled(feature) {
654+
return;
655+
}
656+
657+
// If this item was previously part of a now-stabilized feature which is still
658+
// enabled (i.e. the user hasn't removed the attribute for the stabilized feature
659+
// yet) then allow use of this item.
660+
if let Some(implied_by) = implied_by
661+
&& self.features().enabled(implied_by)
662+
{
663+
return;
664+
}
665+
666+
report_unstable(
667+
self.sess,
668+
feature,
669+
reason.to_opt_reason(),
670+
issue,
671+
None,
672+
false,
673+
span,
674+
|_, _, _| {},
675+
UnstableKind::Const(const_kw_span),
676+
);
677+
}
678+
Some(_) | None => {}
679+
}
680+
}
681+
597682
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
598683
self.lookup_deprecation_entry(id).map(|depr| depr.attr)
599684
}

0 commit comments

Comments
 (0)