Skip to content

Commit c753cef

Browse files
committed
Auto merge of #154976 - jhpratt:rollup-e8XWRVU, r=jhpratt
Rollup of 4 pull requests Successful merges: - #154460 (Deduplication: Pulled common logic out from lower_const_arg_struct) - #154609 (Enable `#[diagnostic::on_const]` for local impls) - #154678 (Introduce #[diagnostic::on_move] on `Rc`) - #154902 (rustdoc: Inherit inline attributes for declarative macros)
2 parents 30d0309 + 084a82e commit c753cef

File tree

17 files changed

+367
-105
lines changed

17 files changed

+367
-105
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ pub struct InherentAssocCandidate {
119119
pub scope: DefId,
120120
}
121121

122+
pub struct ResolvedStructPath<'tcx> {
123+
pub res: Result<Res, ErrorGuaranteed>,
124+
pub ty: Ty<'tcx>,
125+
}
126+
122127
/// A context which can lower type-system entities from the [HIR][hir] to
123128
/// the [`rustc_middle::ty`] representation.
124129
///
@@ -2618,38 +2623,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26182623
ty::Const::new_error(tcx, e)
26192624
};
26202625

2621-
let (ty, variant_did) = match qpath {
2626+
let ResolvedStructPath { res: opt_res, ty } =
2627+
self.lower_path_for_struct_expr(qpath, span, hir_id);
2628+
2629+
let variant_did = match qpath {
26222630
hir::QPath::Resolved(maybe_qself, path) => {
26232631
debug!(?maybe_qself, ?path);
2624-
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
2625-
let ty =
2626-
self.lower_resolved_ty_path(opt_self_ty, path, hir_id, PermitVariants::Yes);
26272632
let variant_did = match path.res {
26282633
Res::Def(DefKind::Variant | DefKind::Struct, did) => did,
26292634
_ => return non_adt_or_variant_res(),
26302635
};
26312636

2632-
(ty, variant_did)
2637+
variant_did
26332638
}
26342639
hir::QPath::TypeRelative(hir_self_ty, segment) => {
26352640
debug!(?hir_self_ty, ?segment);
2636-
let self_ty = self.lower_ty(hir_self_ty);
2637-
let opt_res = self.lower_type_relative_ty_path(
2638-
self_ty,
2639-
hir_self_ty,
2640-
segment,
2641-
hir_id,
2642-
span,
2643-
PermitVariants::Yes,
2644-
);
26452641

2646-
let (ty, _, res_def_id) = match opt_res {
2647-
Ok(r @ (_, DefKind::Variant | DefKind::Struct, _)) => r,
2642+
let res_def_id = match opt_res {
2643+
Ok(r)
2644+
if matches!(
2645+
tcx.def_kind(r.def_id()),
2646+
DefKind::Variant | DefKind::Struct
2647+
) =>
2648+
{
2649+
r.def_id()
2650+
}
26482651
Ok(_) => return non_adt_or_variant_res(),
26492652
Err(e) => return ty::Const::new_error(tcx, e),
26502653
};
26512654

2652-
(ty, res_def_id)
2655+
res_def_id
26532656
}
26542657
};
26552658

@@ -2710,6 +2713,41 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27102713
ty::Const::new_value(tcx, valtree, ty)
27112714
}
27122715

2716+
pub fn lower_path_for_struct_expr(
2717+
&self,
2718+
qpath: hir::QPath<'tcx>,
2719+
path_span: Span,
2720+
hir_id: HirId,
2721+
) -> ResolvedStructPath<'tcx> {
2722+
match qpath {
2723+
hir::QPath::Resolved(ref maybe_qself, path) => {
2724+
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
2725+
let ty = self.lower_resolved_ty_path(self_ty, path, hir_id, PermitVariants::Yes);
2726+
ResolvedStructPath { res: Ok(path.res), ty }
2727+
}
2728+
hir::QPath::TypeRelative(hir_self_ty, segment) => {
2729+
let self_ty = self.lower_ty(hir_self_ty);
2730+
2731+
let result = self.lower_type_relative_ty_path(
2732+
self_ty,
2733+
hir_self_ty,
2734+
segment,
2735+
hir_id,
2736+
path_span,
2737+
PermitVariants::Yes,
2738+
);
2739+
let ty = result
2740+
.map(|(ty, _, _)| ty)
2741+
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
2742+
2743+
ResolvedStructPath {
2744+
res: result.map(|(_, kind, def_id)| Res::Def(kind, def_id)),
2745+
ty,
2746+
}
2747+
}
2748+
}
2749+
}
2750+
27132751
/// Lower a [resolved][hir::QPath::Resolved] path to a (type-level) constant.
27142752
fn lower_resolved_const_path(
27152753
&self,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir::def_id::DefId;
1313
use rustc_hir::intravisit::Visitor;
1414
use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal};
1515
use rustc_hir_analysis::check::potentially_plural_count;
16-
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
16+
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
1717
use rustc_index::IndexVec;
1818
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
1919
use rustc_middle::ty::adjustment::AllowTwoPhase;
@@ -1265,38 +1265,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12651265
path_span: Span,
12661266
hir_id: HirId,
12671267
) -> (Res, LoweredTy<'tcx>) {
1268+
let ResolvedStructPath { res: result, ty } =
1269+
self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
12681270
match *qpath {
1269-
QPath::Resolved(ref maybe_qself, path) => {
1270-
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
1271-
let ty = self.lowerer().lower_resolved_ty_path(
1272-
self_ty,
1273-
path,
1274-
hir_id,
1275-
PermitVariants::Yes,
1276-
);
1277-
(path.res, LoweredTy::from_raw(self, path_span, ty))
1278-
}
1279-
QPath::TypeRelative(hir_self_ty, segment) => {
1280-
let self_ty = self.lower_ty(hir_self_ty);
1281-
1282-
let result = self.lowerer().lower_type_relative_ty_path(
1283-
self_ty.raw,
1284-
hir_self_ty,
1285-
segment,
1286-
hir_id,
1287-
path_span,
1288-
PermitVariants::Yes,
1289-
);
1290-
let ty = result
1291-
.map(|(ty, _, _)| ty)
1292-
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
1271+
QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
1272+
QPath::TypeRelative(_, _) => {
12931273
let ty = LoweredTy::from_raw(self, path_span, ty);
1294-
let result = result.map(|(_, kind, def_id)| (kind, def_id));
1274+
let resolution =
1275+
result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));
12951276

12961277
// Write back the new resolution.
1297-
self.write_resolution(hir_id, result);
1278+
self.write_resolution(hir_id, resolution);
12981279

1299-
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1280+
(result.unwrap_or(Res::Err), ty)
13001281
}
13011282
}
13021283
}

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -882,55 +882,46 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
882882
let trait_name = self.tcx.item_name(trait_did);
883883

884884
if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) {
885-
if let Some(impl_did) = impl_did.as_local()
886-
&& let item = self.tcx.hir_expect_item(impl_did)
887-
&& let hir::ItemKind::Impl(item) = item.kind
888-
&& let Some(of_trait) = item.of_trait
889-
{
890-
// trait is const, impl is local and not const
891-
diag.span_suggestion_verbose(
892-
of_trait.trait_ref.path.span.shrink_to_lo(),
893-
format!("make the `impl` of trait `{trait_name}` `const`"),
894-
"const ".to_string(),
895-
Applicability::MaybeIncorrect,
896-
);
897-
} else {
885+
if !impl_did.is_local() {
898886
diag.span_note(
899887
impl_span,
900888
format!("trait `{trait_name}` is implemented but not `const`"),
901889
);
890+
}
902891

903-
let (condition_options, format_args) = self.on_unimplemented_components(
892+
if let Some(command) =
893+
find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref())
894+
.flatten()
895+
{
896+
let (_, format_args) = self.on_unimplemented_components(
904897
trait_ref,
905898
main_obligation,
906899
diag.long_ty_path(),
907900
);
901+
let CustomDiagnostic { message, label, notes, parent_label: _ } =
902+
command.eval(None, &format_args);
908903

909-
if let Some(command) = find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref()).flatten(){
910-
let note = command.eval(
911-
Some(&condition_options),
912-
&format_args,
913-
);
914-
let CustomDiagnostic {
915-
message,
916-
label,
917-
notes,
918-
parent_label,
919-
} = note;
920-
921-
if let Some(message) = message {
922-
diag.primary_message(message);
923-
}
924-
if let Some(label) = label {
925-
diag.span_label(impl_span, label);
926-
}
927-
for note in notes {
928-
diag.note(note);
929-
}
930-
if let Some(parent_label) = parent_label {
931-
diag.span_label(impl_span, parent_label);
932-
}
904+
if let Some(message) = message {
905+
diag.primary_message(message);
906+
}
907+
if let Some(label) = label {
908+
diag.span_label(span, label);
909+
}
910+
for note in notes {
911+
diag.note(note);
933912
}
913+
} else if let Some(impl_did) = impl_did.as_local()
914+
&& let item = self.tcx.hir_expect_item(impl_did)
915+
&& let hir::ItemKind::Impl(item) = item.kind
916+
&& let Some(of_trait) = item.of_trait
917+
{
918+
// trait is const, impl is local and not const
919+
diag.span_suggestion_verbose(
920+
of_trait.trait_ref.path.span.shrink_to_lo(),
921+
format!("make the `impl` of trait `{trait_name}` `const`"),
922+
"const ".to_string(),
923+
Applicability::MaybeIncorrect,
924+
);
934925
}
935926
}
936927
}

library/alloc/src/rc.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
311311
#[rustc_diagnostic_item = "Rc"]
312312
#[stable(feature = "rust1", since = "1.0.0")]
313313
#[rustc_insignificant_dtor]
314+
#[diagnostic::on_move(
315+
message = "the type `{Self}` does not implement `Copy`",
316+
label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive",
317+
note = "consider using `Rc::clone`"
318+
)]
319+
314320
pub struct Rc<
315321
T: ?Sized,
316322
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,

src/librustdoc/clean/mod.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,35 @@ fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool {
176176
}
177177
}
178178

179+
/// Returns true if `def_id` is a macro and should be inlined.
180+
pub(crate) fn macro_reexport_is_inline(
181+
tcx: TyCtxt<'_>,
182+
import_id: LocalDefId,
183+
def_id: DefId,
184+
) -> bool {
185+
if !matches!(tcx.def_kind(def_id), DefKind::Macro(MacroKinds::BANG)) {
186+
return false;
187+
}
188+
189+
for reexport_def_id in reexport_chain(tcx, import_id, def_id).iter().flat_map(|r| r.id()) {
190+
let is_hidden = tcx.is_doc_hidden(reexport_def_id);
191+
let is_inline = find_attr!(
192+
inline::load_attrs(tcx, reexport_def_id),
193+
Doc(d)
194+
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
195+
);
196+
197+
// hidden takes absolute priority over inline on the same node
198+
if is_hidden {
199+
return false;
200+
}
201+
if is_inline {
202+
return true;
203+
}
204+
}
205+
false
206+
}
207+
179208
fn generate_item_with_correct_attrs(
180209
cx: &mut DocContext<'_>,
181210
kind: ItemKind,
@@ -201,7 +230,8 @@ fn generate_item_with_correct_attrs(
201230
Doc(d)
202231
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
203232
) || (is_glob_import(tcx, import_id)
204-
&& (cx.document_hidden() || !tcx.is_doc_hidden(def_id)));
233+
&& (cx.document_hidden() || !tcx.is_doc_hidden(def_id)))
234+
|| macro_reexport_is_inline(tcx, import_id, def_id);
205235
attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
206236
is_inline = is_inline || import_is_inline;
207237
}

src/librustdoc/visit_ast.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
478478
// If there was a private module in the current path then don't bother inlining
479479
// anything as it will probably be stripped anyway.
480480
if is_pub && self.inside_public_path {
481-
let please_inline = find_attr!(
482-
attrs,
483-
Doc(d)
484-
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
485-
);
481+
let please_inline = if let Some(res_did) = res.opt_def_id()
482+
&& matches!(tcx.def_kind(res_did), DefKind::Macro(MacroKinds::BANG))
483+
{
484+
crate::clean::macro_reexport_is_inline(
485+
tcx,
486+
item.owner_id.def_id,
487+
res_did,
488+
)
489+
} else {
490+
find_attr!(
491+
attrs,
492+
Doc(d)
493+
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
494+
)
495+
};
486496
let ident = match kind {
487497
hir::UseKind::Single(ident) => Some(ident.name),
488498
hir::UseKind::Glob => None,

0 commit comments

Comments
 (0)