Skip to content

Commit bbe9d27

Browse files
committed
Auto merge of #95702 - Dylan-DPC:rollup-793rz6v, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #88025 (ScmCredentials netbsd implementation.) - #95473 (track individual proc-macro expansions in the self-profiler) - #95547 (caution against ptr-to-int transmutes) - #95585 (Explain why `&T` is cloned when `T` is not `Clone`) - #95591 (Use revisions to track NLL test output (part 1)) - #95663 (diagnostics: give a special note for unsafe fn / Fn/FnOnce/FnMut) - #95673 (:arrow_up: rust-analyzer) - #95681 (resolve: Fix resolution of empty paths passed from rustdoc) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 306ba83 + 728f263 commit bbe9d27

File tree

132 files changed

+877
-369
lines changed

Some content is hidden

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

132 files changed

+877
-369
lines changed

compiler/rustc_expand/src/base.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,12 @@ impl<'a> ExtCtxt<'a> {
10471047
self.current_expansion.id.expn_data().call_site
10481048
}
10491049

1050+
/// Returns the current expansion kind's description.
1051+
pub(crate) fn expansion_descr(&self) -> String {
1052+
let expn_data = self.current_expansion.id.expn_data();
1053+
expn_data.kind.descr()
1054+
}
1055+
10501056
/// Equivalent of `Span::def_site` from the proc macro API,
10511057
/// except that the location is taken from the span passed as an argument.
10521058
pub fn with_def_site_ctxt(&self, span: Span) -> Span {

compiler/rustc_expand/src/proc_macro.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ impl base::ProcMacro for BangProcMacro {
2424
span: Span,
2525
input: TokenStream,
2626
) -> Result<TokenStream, ErrorGuaranteed> {
27+
let _timer =
28+
ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
2729
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
2830
let server = proc_macro_server::Rustc::new(ecx);
2931
self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
@@ -48,6 +50,8 @@ impl base::AttrProcMacro for AttrProcMacro {
4850
annotation: TokenStream,
4951
annotated: TokenStream,
5052
) -> Result<TokenStream, ErrorGuaranteed> {
53+
let _timer =
54+
ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
5155
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
5256
let server = proc_macro_server::Rustc::new(ecx);
5357
self.client
@@ -97,17 +101,21 @@ impl MultiItemModifier for ProcMacroDerive {
97101
nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
98102
};
99103

100-
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
101-
let server = proc_macro_server::Rustc::new(ecx);
102-
let stream = match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
103-
Ok(stream) => stream,
104-
Err(e) => {
105-
let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
106-
if let Some(s) = e.as_str() {
107-
err.help(&format!("message: {}", s));
104+
let stream = {
105+
let _timer =
106+
ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
107+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
108+
let server = proc_macro_server::Rustc::new(ecx);
109+
match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
110+
Ok(stream) => stream,
111+
Err(e) => {
112+
let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
113+
if let Some(s) = e.as_str() {
114+
err.help(&format!("message: {}", s));
115+
}
116+
err.emit();
117+
return ExpandResult::Ready(vec![]);
108118
}
109-
err.emit();
110-
return ExpandResult::Ready(vec![]);
111119
}
112120
};
113121

compiler/rustc_resolve/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -3298,7 +3298,9 @@ impl<'a> Resolver<'a> {
32983298
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
32993299
Some(path_res.base_res())
33003300
}
3301-
PathResult::NonModule(..) | PathResult::Failed { .. } => None,
3301+
PathResult::Module(ModuleOrUniformRoot::ExternPrelude)
3302+
| PathResult::NonModule(..)
3303+
| PathResult::Failed { .. } => None,
33023304
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
33033305
}
33043306
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
208208
flags.push((sym::_Self, Some("&[]".to_owned())));
209209
}
210210

211+
if self_ty.is_fn() {
212+
let fn_sig = self_ty.fn_sig(self.tcx);
213+
let shortname = match fn_sig.unsafety() {
214+
hir::Unsafety::Normal => "fn",
215+
hir::Unsafety::Unsafe => "unsafe fn",
216+
};
217+
flags.push((sym::_Self, Some(shortname.to_owned())));
218+
}
219+
211220
if let ty::Array(aty, len) = self_ty.kind() {
212221
flags.push((sym::_Self, Some("[]".to_owned())));
213222
flags.push((sym::_Self, Some(format!("[{}]", aty))));

compiler/rustc_typeck/src/check/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4040
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
4141
self.suggest_missing_parentheses(err, expr);
4242
self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
43+
self.note_type_is_not_clone(err, expected, expr_ty, expr);
4344
self.note_need_for_fn_pointer(err, expected, expr_ty);
4445
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
4546
self.report_closure_inferred_return_type(err, expected);
@@ -630,7 +631,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
630631
Applicability::MachineApplicable,
631632
true,
632633
));
633-
634634
}
635635
}
636636
_ => {}

compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

+54-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ use super::FnCtxt;
22
use crate::astconv::AstConv;
33

44
use rustc_ast::util::parser::ExprPrecedence;
5-
use rustc_span::{self, Span};
6-
75
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
86
use rustc_hir as hir;
97
use rustc_hir::def::{CtorOf, DefKind};
@@ -13,12 +11,14 @@ use rustc_hir::{
1311
WherePredicate,
1412
};
1513
use rustc_infer::infer::{self, TyCtxtInferExt};
16-
14+
use rustc_infer::traits;
1715
use rustc_middle::lint::in_external_macro;
18-
use rustc_middle::ty::{self, Binder, Ty};
16+
use rustc_middle::ty::subst::GenericArgKind;
17+
use rustc_middle::ty::{self, Binder, ToPredicate, Ty};
1918
use rustc_span::symbol::{kw, sym};
19+
use rustc_span::Span;
20+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
2021

21-
use rustc_middle::ty::subst::GenericArgKind;
2222
use std::iter;
2323

2424
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -846,4 +846,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
846846
let node = self.tcx.hir().get(id);
847847
matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. }))
848848
}
849+
850+
/// Suggest that `&T` was cloned instead of `T` because `T` does not implement `Clone`,
851+
/// which is a side-effect of autoref.
852+
pub(crate) fn note_type_is_not_clone(
853+
&self,
854+
diag: &mut Diagnostic,
855+
expected_ty: Ty<'tcx>,
856+
found_ty: Ty<'tcx>,
857+
expr: &hir::Expr<'_>,
858+
) {
859+
let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; };
860+
let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; };
861+
let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return };
862+
let results = self.typeck_results.borrow();
863+
// First, look for a `Clone::clone` call
864+
if segment.ident.name == sym::clone
865+
&& results.type_dependent_def_id(expr.hir_id).map_or(
866+
false,
867+
|did| {
868+
self.tcx.associated_item(did).container
869+
== ty::AssocItemContainer::TraitContainer(clone_trait_did)
870+
},
871+
)
872+
// If that clone call hasn't already dereferenced the self type (i.e. don't give this
873+
// diagnostic in cases where we have `(&&T).clone()` and we expect `T`).
874+
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
875+
// Check that we're in fact trying to clone into the expected type
876+
&& self.can_coerce(*pointee_ty, expected_ty)
877+
// And the expected type doesn't implement `Clone`
878+
&& !self.predicate_must_hold_considering_regions(&traits::Obligation {
879+
cause: traits::ObligationCause::dummy(),
880+
param_env: self.param_env,
881+
recursion_depth: 0,
882+
predicate: ty::Binder::dummy(ty::TraitRef {
883+
def_id: clone_trait_did,
884+
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
885+
})
886+
.without_const()
887+
.to_predicate(self.tcx),
888+
})
889+
{
890+
diag.span_note(
891+
callee_expr.span,
892+
&format!(
893+
"`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
894+
),
895+
);
896+
}
897+
}
849898
}

library/core/src/intrinsics.rs

+10
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,16 @@ extern "rust-intrinsic" {
991991
/// let ptr_num_cast = ptr as *const i32 as usize;
992992
/// ```
993993
///
994+
/// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined
995+
/// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave
996+
/// as expected -- this is touching on many unspecified aspects of the Rust memory model.
997+
/// Depending on what the code is doing, the following alternatives are preferrable to
998+
/// pointer-to-integer transmutation:
999+
/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a
1000+
/// type for that buffer, it can use [`MaybeUninit`][mem::MaybeUninit].
1001+
/// - If the code actually wants to work on the address the pointer points to, it can use `as`
1002+
/// casts or [`ptr.addr()`][pointer::addr].
1003+
///
9941004
/// Turning a `*mut T` into an `&mut T`:
9951005
///
9961006
/// ```

library/core/src/ops/function.rs

+18
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
Args = "()",
6161
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
6262
),
63+
on(
64+
_Self = "unsafe fn",
65+
note = "unsafe function cannot be called generically without an unsafe block",
66+
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
67+
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
68+
),
6369
message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
6470
label = "expected an `Fn<{Args}>` closure, found `{Self}`"
6571
)]
@@ -141,6 +147,12 @@ pub trait Fn<Args>: FnMut<Args> {
141147
Args = "()",
142148
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
143149
),
150+
on(
151+
_Self = "unsafe fn",
152+
note = "unsafe function cannot be called generically without an unsafe block",
153+
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
154+
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
155+
),
144156
message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
145157
label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
146158
)]
@@ -214,6 +226,12 @@ pub trait FnMut<Args>: FnOnce<Args> {
214226
Args = "()",
215227
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
216228
),
229+
on(
230+
_Self = "unsafe fn",
231+
note = "unsafe function cannot be called generically without an unsafe block",
232+
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
233+
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
234+
),
217235
message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
218236
label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
219237
)]

0 commit comments

Comments
 (0)