Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
72 changes: 55 additions & 17 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ pub struct InherentAssocCandidate {
pub scope: DefId,
}

pub struct ResolvedStructPath<'tcx> {
pub res: Result<Res, ErrorGuaranteed>,
pub ty: Ty<'tcx>,
}

/// A context which can lower type-system entities from the [HIR][hir] to
/// the [`rustc_middle::ty`] representation.
///
Expand Down Expand Up @@ -2618,38 +2623,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::new_error(tcx, e)
};

let (ty, variant_did) = match qpath {
let ResolvedStructPath { res: opt_res, ty } =
self.lower_path_for_struct_expr(qpath, span, hir_id);

let variant_did = match qpath {
hir::QPath::Resolved(maybe_qself, path) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
let ty =
self.lower_resolved_ty_path(opt_self_ty, path, hir_id, PermitVariants::Yes);
let variant_did = match path.res {
Res::Def(DefKind::Variant | DefKind::Struct, did) => did,
_ => return non_adt_or_variant_res(),
};

(ty, variant_did)
variant_did
}
hir::QPath::TypeRelative(hir_self_ty, segment) => {
debug!(?hir_self_ty, ?segment);
let self_ty = self.lower_ty(hir_self_ty);
let opt_res = self.lower_type_relative_ty_path(
self_ty,
hir_self_ty,
segment,
hir_id,
span,
PermitVariants::Yes,
);

let (ty, _, res_def_id) = match opt_res {
Ok(r @ (_, DefKind::Variant | DefKind::Struct, _)) => r,
let res_def_id = match opt_res {
Ok(r)
if matches!(
tcx.def_kind(r.def_id()),
DefKind::Variant | DefKind::Struct
) =>
{
r.def_id()
}
Ok(_) => return non_adt_or_variant_res(),
Err(e) => return ty::Const::new_error(tcx, e),
};

(ty, res_def_id)
res_def_id
}
};

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

pub fn lower_path_for_struct_expr(
&self,
qpath: hir::QPath<'tcx>,
path_span: Span,
hir_id: HirId,
) -> ResolvedStructPath<'tcx> {
match qpath {
hir::QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
let ty = self.lower_resolved_ty_path(self_ty, path, hir_id, PermitVariants::Yes);
ResolvedStructPath { res: Ok(path.res), ty }
}
hir::QPath::TypeRelative(hir_self_ty, segment) => {
let self_ty = self.lower_ty(hir_self_ty);

let result = self.lower_type_relative_ty_path(
self_ty,
hir_self_ty,
segment,
hir_id,
path_span,
PermitVariants::Yes,
);
let ty = result
.map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));

ResolvedStructPath {
res: result.map(|(_, kind, def_id)| Res::Def(kind, def_id)),
ty,
}
}
}
}

/// Lower a [resolved][hir::QPath::Resolved] path to a (type-level) constant.
fn lower_resolved_const_path(
&self,
Expand Down
37 changes: 9 additions & 28 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal};
use rustc_hir_analysis::check::potentially_plural_count;
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
use rustc_index::IndexVec;
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
use rustc_middle::ty::adjustment::AllowTwoPhase;
Expand Down Expand Up @@ -1265,38 +1265,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path_span: Span,
hir_id: HirId,
) -> (Res, LoweredTy<'tcx>) {
let ResolvedStructPath { res: result, ty } =
self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
match *qpath {
QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
let ty = self.lowerer().lower_resolved_ty_path(
self_ty,
path,
hir_id,
PermitVariants::Yes,
);
(path.res, LoweredTy::from_raw(self, path_span, ty))
}
QPath::TypeRelative(hir_self_ty, segment) => {
let self_ty = self.lower_ty(hir_self_ty);

let result = self.lowerer().lower_type_relative_ty_path(
self_ty.raw,
hir_self_ty,
segment,
hir_id,
path_span,
PermitVariants::Yes,
);
let ty = result
.map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
QPath::TypeRelative(_, _) => {
let ty = LoweredTy::from_raw(self, path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id));
let resolution =
result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));

// Write back the new resolution.
self.write_resolution(hir_id, result);
self.write_resolution(hir_id, resolution);

(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
(result.unwrap_or(Res::Err), ty)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -882,55 +882,46 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let trait_name = self.tcx.item_name(trait_did);

if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) {
if let Some(impl_did) = impl_did.as_local()
&& let item = self.tcx.hir_expect_item(impl_did)
&& let hir::ItemKind::Impl(item) = item.kind
&& let Some(of_trait) = item.of_trait
{
// trait is const, impl is local and not const
diag.span_suggestion_verbose(
of_trait.trait_ref.path.span.shrink_to_lo(),
format!("make the `impl` of trait `{trait_name}` `const`"),
"const ".to_string(),
Applicability::MaybeIncorrect,
);
} else {
if !impl_did.is_local() {
diag.span_note(
impl_span,
format!("trait `{trait_name}` is implemented but not `const`"),
);
}

let (condition_options, format_args) = self.on_unimplemented_components(
if let Some(command) =
find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref())
.flatten()
{
let (_, format_args) = self.on_unimplemented_components(
trait_ref,
main_obligation,
diag.long_ty_path(),
);
let CustomDiagnostic { message, label, notes, parent_label: _ } =
command.eval(None, &format_args);

if let Some(command) = find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref()).flatten(){
let note = command.eval(
Some(&condition_options),
&format_args,
);
let CustomDiagnostic {
message,
label,
notes,
parent_label,
} = note;

if let Some(message) = message {
diag.primary_message(message);
}
if let Some(label) = label {
diag.span_label(impl_span, label);
}
for note in notes {
diag.note(note);
}
if let Some(parent_label) = parent_label {
diag.span_label(impl_span, parent_label);
}
if let Some(message) = message {
diag.primary_message(message);
}
if let Some(label) = label {
diag.span_label(span, label);
}
for note in notes {
diag.note(note);
}
} else if let Some(impl_did) = impl_did.as_local()
&& let item = self.tcx.hir_expect_item(impl_did)
&& let hir::ItemKind::Impl(item) = item.kind
&& let Some(of_trait) = item.of_trait
{
// trait is const, impl is local and not const
diag.span_suggestion_verbose(
of_trait.trait_ref.path.span.shrink_to_lo(),
format!("make the `impl` of trait `{trait_name}` `const`"),
"const ".to_string(),
Applicability::MaybeIncorrect,
);
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,12 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
#[rustc_diagnostic_item = "Rc"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_insignificant_dtor]
#[diagnostic::on_move(
message = "the type `{Self}` does not implement `Copy`",
label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive",
note = "consider using `Rc::clone`"
)]

pub struct Rc<
T: ?Sized,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
Expand Down
32 changes: 31 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,35 @@ fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool {
}
}

/// Returns true if `def_id` is a macro and should be inlined.
pub(crate) fn macro_reexport_is_inline(
tcx: TyCtxt<'_>,
import_id: LocalDefId,
def_id: DefId,
) -> bool {
if !matches!(tcx.def_kind(def_id), DefKind::Macro(MacroKinds::BANG)) {
return false;
}

for reexport_def_id in reexport_chain(tcx, import_id, def_id).iter().flat_map(|r| r.id()) {
let is_hidden = tcx.is_doc_hidden(reexport_def_id);
let is_inline = find_attr!(
inline::load_attrs(tcx, reexport_def_id),
Doc(d)
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
);

// hidden takes absolute priority over inline on the same node
if is_hidden {
return false;
}
if is_inline {
return true;
}
}
false
}

fn generate_item_with_correct_attrs(
cx: &mut DocContext<'_>,
kind: ItemKind,
Expand All @@ -201,7 +230,8 @@ fn generate_item_with_correct_attrs(
Doc(d)
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
) || (is_glob_import(tcx, import_id)
&& (cx.document_hidden() || !tcx.is_doc_hidden(def_id)));
&& (cx.document_hidden() || !tcx.is_doc_hidden(def_id)))
|| macro_reexport_is_inline(tcx, import_id, def_id);
attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
is_inline = is_inline || import_is_inline;
}
Expand Down
20 changes: 15 additions & 5 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,11 +478,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway.
if is_pub && self.inside_public_path {
let please_inline = find_attr!(
attrs,
Doc(d)
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
);
let please_inline = if let Some(res_did) = res.opt_def_id()
&& matches!(tcx.def_kind(res_did), DefKind::Macro(MacroKinds::BANG))
{
crate::clean::macro_reexport_is_inline(
tcx,
item.owner_id.def_id,
res_did,
)
} else {
find_attr!(
attrs,
Doc(d)
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
)
};
let ident = match kind {
hir::UseKind::Single(ident) => Some(ident.name),
hir::UseKind::Glob => None,
Expand Down
Loading
Loading