Skip to content

Rollup of 7 pull requests #92931

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 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8bdf5c3
Implement panic::update_hook
Badel2 Jan 5, 2022
8ef3ce8
Change panic::update_hook to simplify usage
Badel2 Jan 7, 2022
0c58586
Add safety comments to panic::(set/take/update)_hook
Badel2 Jan 7, 2022
4c3e330
feat: pass_by_value lint attribute
mdibaiee Jan 7, 2022
91ed689
rustc_pass_by_value lint: add test on custom types
mdibaiee Jan 10, 2022
71e3314
rustc_pass_by_value remove dependency on rustc_diagnostic_item
mdibaiee Jan 10, 2022
49553bb
Remove hack that is no longer necessary
camelid Jan 6, 2022
e18b23b
Move two intra-doc-link tests into the `intra-doc` folder
camelid Jan 6, 2022
ca20d64
Enable ignored part of test
camelid Jan 6, 2022
977a7ca
Add test for disambiguator mismatch with crate
camelid Jan 6, 2022
9acd813
Use Res instead of Disambiguator for `resolved` in `report_mismatch`
camelid Jan 6, 2022
591ec49
Remove unnecessary conditional for suggesting disambiguator
camelid Jan 6, 2022
a5f09f7
Update comment and make code clearer
camelid Jan 6, 2022
895fa9c
Extract functions for two closures
camelid Jan 6, 2022
28d2353
Update some comments post the side channel removal
camelid Jan 6, 2022
a6762e9
rustc_pass_by_value: allow types with no parameters on self
mdibaiee Jan 11, 2022
959bf2b
rustc_pass_by_value: handle generic and const type parameters
mdibaiee Jan 11, 2022
2728af7
rustc_pass_by_value: handle inferred generic types (with _)
mdibaiee Jan 11, 2022
c84f2b2
Remove some unnecessary uses of `FieldDef::ident`
camelid Jan 12, 2022
9625829
remove unused FIXME
lcnr Jan 12, 2022
51d7665
rustdoc: remove hand-rolled isatty
euclio Jan 12, 2022
9ff8ae0
rustdoc: fix intra-link for generic trait impls
mdibaiee Jan 11, 2022
ae20500
rustdoc: add intra-doc trait impl test for extern types
mdibaiee Jan 13, 2022
7f29b1f
Rollup merge of #92598 - Badel2:panic-update-hook, r=yaahc
matthiaskrgr Jan 15, 2022
bcd2ad5
Rollup merge of #92635 - camelid:yet-more-cleanup, r=Manishearth
matthiaskrgr Jan 15, 2022
a07d466
Rollup merge of #92646 - mdibaiee:76935/pass-by-value, r=lcnr
matthiaskrgr Jan 15, 2022
f0b7d8f
Rollup merge of #92792 - mdibaiee:92662/fix-intra-doc-generics, r=cam…
matthiaskrgr Jan 15, 2022
13b802c
Rollup merge of #92799 - rust-lang:followup-from-92533, r=Aaron1011
matthiaskrgr Jan 15, 2022
7f9f19d
Rollup merge of #92814 - lcnr:unused-fixme, r=Mark-Simulacrum
matthiaskrgr Jan 15, 2022
96d0d0f
Rollup merge of #92819 - euclio:atty, r=CraftSpider
matthiaskrgr Jan 15, 2022
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
Prev Previous commit
Next Next commit
feat: pass_by_value lint attribute
Useful for thin wrapper attributes that are best passed as value instead
of reference.
  • Loading branch information
mdibaiee committed Jan 9, 2022
commit 4c3e330a8c023af20beb23a3a46b5d6d77a62839
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
"language items are subject to change",
),
rustc_attr!(
rustc_pass_by_value, Normal,
template!(Word, NameValueStr: "reason"), WarnFollowing,
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
),
BuiltinAttribute {
name: sym::rustc_diagnostic_item,
type_: Normal,
Expand Down
33 changes: 1 addition & 32 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{
GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
TyKind,
};
use rustc_hir::{GenericArg, HirId, Item, ItemKind, Node, Path, PathSegment, QPath, Ty, TyKind};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind};
Expand Down Expand Up @@ -58,13 +55,6 @@ declare_tool_lint! {
report_in_external_macro: true
}

declare_tool_lint! {
pub rustc::TY_PASS_BY_REFERENCE,
Allow,
"passing `Ty` or `TyCtxt` by reference",
report_in_external_macro: true
}

declare_tool_lint! {
pub rustc::USAGE_OF_QUALIFIED_TY,
Allow,
Expand All @@ -74,7 +64,6 @@ declare_tool_lint! {

declare_lint_pass!(TyTyKind => [
USAGE_OF_TY_TYKIND,
TY_PASS_BY_REFERENCE,
USAGE_OF_QUALIFIED_TY,
]);

Expand Down Expand Up @@ -131,26 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
}
}
}
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
if cx.tcx.impl_trait_ref(impl_did).is_some() {
return;
}
}
if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) {
cx.struct_span_lint(TY_PASS_BY_REFERENCE, ty.span, |lint| {
lint.build(&format!("passing `{}` by reference", t))
.span_suggestion(
ty.span,
"try passing by value",
t,
// Changing type of function argument
Applicability::MaybeIncorrect,
)
.emit();
})
}
}
_ => {}
}
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ mod non_ascii_idents;
mod non_fmt_panic;
mod nonstandard_style;
mod noop_method_call;
mod pass_by_value;
mod passes;
mod redundant_semicolon;
mod traits;
Expand Down Expand Up @@ -85,6 +86,7 @@ use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use nonstandard_style::*;
use noop_method_call::*;
use pass_by_value::*;
use redundant_semicolon::*;
use traits::*;
use types::*;
Expand Down Expand Up @@ -489,15 +491,17 @@ fn register_internals(store: &mut LintStore) {
store.register_late_pass(|| Box::new(ExistingDocKeyword));
store.register_lints(&TyTyKind::get_lints());
store.register_late_pass(|| Box::new(TyTyKind));
store.register_lints(&PassByValue::get_lints());
store.register_late_pass(|| Box::new(PassByValue));
store.register_group(
false,
"rustc::internal",
None,
vec![
LintId::of(DEFAULT_HASH_TYPES),
LintId::of(USAGE_OF_TY_TYKIND),
LintId::of(PASS_BY_VALUE),
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
LintId::of(TY_PASS_BY_REFERENCE),
LintId::of(USAGE_OF_QUALIFIED_TY),
LintId::of(EXISTING_DOC_KEYWORD),
],
Expand Down
103 changes: 103 additions & 0 deletions compiler/rustc_lint/src/pass_by_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use crate::{LateContext, LateLintPass, LintContext};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
use rustc_middle::ty;
use rustc_span::symbol::sym;

declare_tool_lint! {
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to always be passed by value.
/// This is usually used for types that are thin wrappers around references, so there is no benefit to an extra
/// layer of indirection. (Example: `Ty` which is a reference to a `TyS`)
pub rustc::PASS_BY_VALUE,
Warn,
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
report_in_external_macro: true
}

declare_lint_pass!(PassByValue => [PASS_BY_VALUE]);

impl<'tcx> LateLintPass<'tcx> for PassByValue {
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
match &ty.kind {
TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
if cx.tcx.impl_trait_ref(impl_did).is_some() {
return;
}
}
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
lint.build(&format!("passing `{}` by reference", t))
.span_suggestion(
ty.span,
"try passing by value",
t,
// Changing type of function argument
Applicability::MaybeIncorrect,
)
.emit();
})
}
}
_ => {}
}
}
}

fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
match path.res {
Res::Def(_, def_id) if has_pass_by_value_attr(cx, def_id) => {
if let Some(name) = cx.tcx.get_diagnostic_name(def_id) {
return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap())));
}
}
Res::SelfTy(None, Some((did, _))) => {
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
if has_pass_by_value_attr(cx, adt.did) {
if let Some(name) = cx.tcx.get_diagnostic_name(adt.did) {
return Some(format!("{}<{}>", name, substs[0]));
}
}
}
}
_ => (),
}
}

None
}

fn has_pass_by_value_attr(cx: &LateContext<'_>, def_id: DefId) -> bool {
for attr in cx.tcx.get_attrs(def_id).iter() {
if attr.has_name(sym::rustc_pass_by_value) {
return true;
}
}
false
}

fn gen_args(segment: &PathSegment<'_>) -> String {
if let Some(args) = &segment.args {
let lifetimes = args
.args
.iter()
.filter_map(|arg| {
if let GenericArg::Lifetime(lt) = arg {
Some(lt.name.ident().to_string())
} else {
None
}
})
.collect::<Vec<_>>();

if !lifetimes.is_empty() {
return format!("<{}>", lifetimes.join(", "));
}
}

String::new()
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,7 @@ pub struct FreeRegionInfo {
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
#[derive(Copy, Clone)]
#[rustc_diagnostic_item = "TyCtxt"]
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
pub struct TyCtxt<'tcx> {
gcx: &'tcx GlobalCtxt<'tcx>,
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
}

#[rustc_diagnostic_item = "Ty"]
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
pub type Ty<'tcx> = &'tcx TyS<'tcx>;

impl ty::EarlyBoundRegion {
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl CheckAttrVisitor<'_> {
}
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
Expand Down Expand Up @@ -1066,6 +1067,29 @@ impl CheckAttrVisitor<'_> {
is_valid
}

/// Warns against some misuses of `#[pass_by_value]`
fn check_pass_by_value(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target {
Target::Struct
| Target::Enum
| Target::Union
| Target::Trait
| Target::TraitAlias
| Target::TyAlias => true,
_ => {
self.tcx
.sess
.struct_span_err(
attr.span,
"`pass_by_value` attribute should be applied to a struct, enum, trait or type alias.",
)
.span_label(*span, "is not a struct, enum, trait or type alias")
.emit();
false
}
}
}

/// Warns against some misuses of `#[must_use]`
fn check_must_use(
&self,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,7 @@ symbols! {
rustc_paren_sugar,
rustc_partition_codegened,
rustc_partition_reused,
rustc_pass_by_value,
rustc_peek,
rustc_peek_definite_init,
rustc_peek_liveness,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// compile-flags: -Z unstable-options

#![feature(rustc_private)]
#![deny(rustc::ty_pass_by_reference)]
#![deny(rustc::pass_by_value)]
#![allow(unused)]

extern crate rustc_middle;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,77 +1,77 @@
error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:13:13
--> $DIR/rustc_pass_by_value.rs:13:13
|
LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
note: the lint level is defined here
--> $DIR/pass_ty_by_ref.rs:4:9
--> $DIR/rustc_pass_by_value.rs:4:9
|
LL | #![deny(rustc::ty_pass_by_reference)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #![deny(rustc::pass_by_value)]
| ^^^^^^^^^^^^^^^^^^^^

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:15:18
--> $DIR/rustc_pass_by_value.rs:15:18
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`

error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:19:28
--> $DIR/rustc_pass_by_value.rs:19:28
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^ help: try passing by value: `Ty<'_>`

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:19:55
--> $DIR/rustc_pass_by_value.rs:19:55
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`

error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:26:17
--> $DIR/rustc_pass_by_value.rs:26:17
|
LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>`

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:28:22
--> $DIR/rustc_pass_by_value.rs:28:22
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`

error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:31:41
--> $DIR/rustc_pass_by_value.rs:31:41
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
| ^^^^^^^ help: try passing by value: `Ty<'_>`

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:31:68
--> $DIR/rustc_pass_by_value.rs:31:68
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`

error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:53:17
--> $DIR/rustc_pass_by_value.rs:53:17
|
LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>`

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:55:22
--> $DIR/rustc_pass_by_value.rs:55:22
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`

error: passing `Ty<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:59:38
--> $DIR/rustc_pass_by_value.rs:59:38
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^ help: try passing by value: `Ty<'_>`

error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:59:65
--> $DIR/rustc_pass_by_value.rs:59:65
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
Expand Down
Loading