Skip to content

Commit bd3cb52

Browse files
committed
Auto merge of #92970 - matthiaskrgr:rollup-tcx7cfb, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #92487 (Fix unclosed boxes in pretty printing of TraitAlias) - #92581 (ARMv6K Horizon - Enable default libraries) - #92619 (Add diagnostic items for macros) - #92635 (rustdoc: Yet more intra-doc links cleanup) - #92646 (feat: rustc_pass_by_value lint attribute) - #92706 (Clarify explicitly that BTree{Map,Set} are ordered.) - #92710 (Include Projections when elaborating TypeOutlives) - #92746 (Parse `Ty?` as `Option<Ty>` and provide structured suggestion) - #92792 (rustdoc: fix intra-link for generic trait impls) - #92814 (remove unused FIXME) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 48e89b0 + 2b6b49e commit bd3cb52

Some content is hidden

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

51 files changed

+906
-362
lines changed

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1357,9 +1357,7 @@ impl<'a> State<'a> {
13571357
self.bclose(item.span, empty);
13581358
}
13591359
ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
1360-
self.head("");
1361-
self.print_visibility(&item.vis);
1362-
self.word_nbsp("trait");
1360+
self.head(visibility_qualified(&item.vis, "trait"));
13631361
self.print_ident(item.ident);
13641362
self.print_generic_params(&generics.params);
13651363
let mut real_bounds = Vec::with_capacity(bounds.len());
@@ -1377,6 +1375,8 @@ impl<'a> State<'a> {
13771375
self.print_type_bounds("=", &real_bounds);
13781376
self.print_where_clause(&generics.where_clause);
13791377
self.word(";");
1378+
self.end(); // end inner head-block
1379+
self.end(); // end outer head-block
13801380
}
13811381
ast::ItemKind::MacCall(ref mac) => {
13821382
self.print_mac(mac);

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
623623
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
624624
"language items are subject to change",
625625
),
626+
rustc_attr!(
627+
rustc_pass_by_value, Normal,
628+
template!(Word), WarnFollowing,
629+
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
630+
),
626631
BuiltinAttribute {
627632
name: sym::rustc_diagnostic_item,
628633
type_: Normal,

Diff for: compiler/rustc_hir_pretty/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,7 @@ impl<'a> State<'a> {
705705
self.bclose(item.span);
706706
}
707707
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
708-
self.head("");
709-
self.print_visibility(&item.vis);
710-
self.word_nbsp("trait");
708+
self.head(visibility_qualified(&item.vis, "trait"));
711709
self.print_ident(item.ident);
712710
self.print_generic_params(&generics.params);
713711
let mut real_bounds = Vec::with_capacity(bounds.len());
@@ -725,6 +723,8 @@ impl<'a> State<'a> {
725723
self.print_bounds("=", real_bounds);
726724
self.print_where_clause(&generics.where_clause);
727725
self.word(";");
726+
self.end(); // end inner head-block
727+
self.end(); // end outer head-block
728728
}
729729
}
730730
self.ann.post(self, AnnNode::Item(item))

Diff for: compiler/rustc_index/src/lib.rs

-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,3 @@
99
pub mod bit_set;
1010
pub mod interval;
1111
pub mod vec;
12-
13-
// FIXME(#56935): Work around ICEs during cross-compilation.
14-
#[allow(unused)]
15-
extern crate rustc_macros;

Diff for: compiler/rustc_infer/src/infer/outlives/obligations.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
164164
"cannot process registered region obligations in a snapshot"
165165
);
166166

167-
debug!("process_registered_region_obligations()");
167+
debug!(?param_env, "process_registered_region_obligations()");
168168

169169
let my_region_obligations = self.take_registered_region_obligations();
170170

@@ -356,6 +356,8 @@ where
356356
let trait_bounds: Vec<_> =
357357
self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect();
358358

359+
debug!(?trait_bounds);
360+
359361
// Compute the bounds we can derive from the environment. This
360362
// is an "approximate" match -- in some cases, these bounds
361363
// may not apply.

Diff for: compiler/rustc_infer/src/traits/util.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,19 @@ impl<'tcx> Elaborator<'tcx> {
241241

242242
Component::UnresolvedInferenceVariable(_) => None,
243243

244-
Component::Projection(_) | Component::EscapingProjection(_) => {
245-
// We can probably do more here. This
246-
// corresponds to a case like `<T as
247-
// Foo<'a>>::U: 'b`.
244+
Component::Projection(projection) => {
245+
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
246+
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
247+
let ty =
248+
tcx.mk_projection(projection.item_def_id, projection.substs);
249+
Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
250+
ty, r_min,
251+
)))
252+
}
253+
254+
Component::EscapingProjection(_) => {
255+
// We might be able to do more here, but we don't
256+
// want to deal with escaping vars right now.
248257
None
249258
}
250259
})

Diff for: compiler/rustc_lint/src/internal.rs

+1-32
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
55
use rustc_ast as ast;
66
use rustc_errors::Applicability;
77
use rustc_hir::def::Res;
8-
use rustc_hir::{
9-
GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
10-
TyKind,
11-
};
8+
use rustc_hir::{GenericArg, HirId, Item, ItemKind, Node, Path, PathSegment, QPath, Ty, TyKind};
129
use rustc_middle::ty;
1310
use rustc_session::{declare_lint_pass, declare_tool_lint};
1411
use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -58,13 +55,6 @@ declare_tool_lint! {
5855
report_in_external_macro: true
5956
}
6057

61-
declare_tool_lint! {
62-
pub rustc::TY_PASS_BY_REFERENCE,
63-
Allow,
64-
"passing `Ty` or `TyCtxt` by reference",
65-
report_in_external_macro: true
66-
}
67-
6858
declare_tool_lint! {
6959
pub rustc::USAGE_OF_QUALIFIED_TY,
7060
Allow,
@@ -74,7 +64,6 @@ declare_tool_lint! {
7464

7565
declare_lint_pass!(TyTyKind => [
7666
USAGE_OF_TY_TYKIND,
77-
TY_PASS_BY_REFERENCE,
7867
USAGE_OF_QUALIFIED_TY,
7968
]);
8069

@@ -131,26 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
131120
}
132121
}
133122
}
134-
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
135-
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
136-
if cx.tcx.impl_trait_ref(impl_did).is_some() {
137-
return;
138-
}
139-
}
140-
if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) {
141-
cx.struct_span_lint(TY_PASS_BY_REFERENCE, ty.span, |lint| {
142-
lint.build(&format!("passing `{}` by reference", t))
143-
.span_suggestion(
144-
ty.span,
145-
"try passing by value",
146-
t,
147-
// Changing type of function argument
148-
Applicability::MaybeIncorrect,
149-
)
150-
.emit();
151-
})
152-
}
153-
}
154123
_ => {}
155124
}
156125
}

Diff for: compiler/rustc_lint/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ mod non_ascii_idents;
5656
mod non_fmt_panic;
5757
mod nonstandard_style;
5858
mod noop_method_call;
59+
mod pass_by_value;
5960
mod passes;
6061
mod redundant_semicolon;
6162
mod traits;
@@ -85,6 +86,7 @@ use non_ascii_idents::*;
8586
use non_fmt_panic::NonPanicFmt;
8687
use nonstandard_style::*;
8788
use noop_method_call::*;
89+
use pass_by_value::*;
8890
use redundant_semicolon::*;
8991
use traits::*;
9092
use types::*;
@@ -490,15 +492,17 @@ fn register_internals(store: &mut LintStore) {
490492
store.register_late_pass(|| Box::new(ExistingDocKeyword));
491493
store.register_lints(&TyTyKind::get_lints());
492494
store.register_late_pass(|| Box::new(TyTyKind));
495+
store.register_lints(&PassByValue::get_lints());
496+
store.register_late_pass(|| Box::new(PassByValue));
493497
store.register_group(
494498
false,
495499
"rustc::internal",
496500
None,
497501
vec![
498502
LintId::of(DEFAULT_HASH_TYPES),
499503
LintId::of(USAGE_OF_TY_TYKIND),
504+
LintId::of(PASS_BY_VALUE),
500505
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
501-
LintId::of(TY_PASS_BY_REFERENCE),
502506
LintId::of(USAGE_OF_QUALIFIED_TY),
503507
LintId::of(EXISTING_DOC_KEYWORD),
504508
],

Diff for: compiler/rustc_lint/src/pass_by_value.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use crate::{LateContext, LateLintPass, LintContext};
2+
use rustc_errors::Applicability;
3+
use rustc_hir as hir;
4+
use rustc_hir::def::Res;
5+
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
6+
use rustc_middle::ty;
7+
use rustc_span::symbol::sym;
8+
9+
declare_tool_lint! {
10+
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to always be passed by value.
11+
/// This is usually used for types that are thin wrappers around references, so there is no benefit to an extra
12+
/// layer of indirection. (Example: `Ty` which is a reference to a `TyS`)
13+
pub rustc::PASS_BY_VALUE,
14+
Warn,
15+
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
16+
report_in_external_macro: true
17+
}
18+
19+
declare_lint_pass!(PassByValue => [PASS_BY_VALUE]);
20+
21+
impl<'tcx> LateLintPass<'tcx> for PassByValue {
22+
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
23+
match &ty.kind {
24+
TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
25+
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
26+
if cx.tcx.impl_trait_ref(impl_did).is_some() {
27+
return;
28+
}
29+
}
30+
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
31+
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
32+
lint.build(&format!("passing `{}` by reference", t))
33+
.span_suggestion(
34+
ty.span,
35+
"try passing by value",
36+
t,
37+
// Changing type of function argument
38+
Applicability::MaybeIncorrect,
39+
)
40+
.emit();
41+
})
42+
}
43+
}
44+
_ => {}
45+
}
46+
}
47+
}
48+
49+
fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
50+
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
51+
match path.res {
52+
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
53+
let name = cx.tcx.item_name(def_id).to_ident_string();
54+
let path_segment = path.segments.last().unwrap();
55+
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
56+
}
57+
Res::SelfTy(None, Some((did, _))) => {
58+
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
59+
if cx.tcx.has_attr(adt.did, sym::rustc_pass_by_value) {
60+
return Some(cx.tcx.def_path_str_with_substs(adt.did, substs));
61+
}
62+
}
63+
}
64+
_ => (),
65+
}
66+
}
67+
68+
None
69+
}
70+
71+
fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
72+
if let Some(args) = &segment.args {
73+
let params = args
74+
.args
75+
.iter()
76+
.map(|arg| match arg {
77+
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
78+
GenericArg::Type(ty) => {
79+
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default()
80+
}
81+
GenericArg::Const(c) => {
82+
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default()
83+
}
84+
GenericArg::Infer(_) => String::from("_"),
85+
})
86+
.collect::<Vec<_>>();
87+
88+
if !params.is_empty() {
89+
return format!("<{}>", params.join(", "));
90+
}
91+
}
92+
93+
String::new()
94+
}

Diff for: compiler/rustc_middle/src/ty/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ pub struct FreeRegionInfo {
961961
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
962962
#[derive(Copy, Clone)]
963963
#[rustc_diagnostic_item = "TyCtxt"]
964+
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
964965
pub struct TyCtxt<'tcx> {
965966
gcx: &'tcx GlobalCtxt<'tcx>,
966967
}

Diff for: compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
464464
}
465465

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

469470
impl ty::EarlyBoundRegion {

Diff for: compiler/rustc_parse/src/parser/diagnostics.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::pat::Expected;
2-
use super::ty::AllowPlus;
2+
use super::ty::{AllowPlus, IsAsCast};
33
use super::{
44
BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
55
TokenExpectType, TokenType,
@@ -1032,6 +1032,34 @@ impl<'a> Parser<'a> {
10321032
}
10331033
}
10341034

1035+
/// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
1036+
pub(super) fn maybe_recover_from_question_mark(
1037+
&mut self,
1038+
ty: P<Ty>,
1039+
is_as_cast: IsAsCast,
1040+
) -> P<Ty> {
1041+
if let IsAsCast::Yes = is_as_cast {
1042+
return ty;
1043+
}
1044+
if self.token == token::Question {
1045+
self.bump();
1046+
self.struct_span_err(self.prev_token.span, "invalid `?` in type")
1047+
.span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
1048+
.multipart_suggestion(
1049+
"if you meant to express that the type might not contain a value, use the `Option` wrapper type",
1050+
vec![
1051+
(ty.span.shrink_to_lo(), "Option<".to_string()),
1052+
(self.prev_token.span, ">".to_string()),
1053+
],
1054+
Applicability::MachineApplicable,
1055+
)
1056+
.emit();
1057+
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
1058+
} else {
1059+
ty
1060+
}
1061+
}
1062+
10351063
pub(super) fn maybe_recover_from_bad_type_plus(
10361064
&mut self,
10371065
allow_plus: AllowPlus,

Diff for: compiler/rustc_parse/src/parser/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ impl<'a> Parser<'a> {
682682
// Save the state of the parser before parsing type normally, in case there is a
683683
// LessThan comparison after this cast.
684684
let parser_snapshot_before_type = self.clone();
685-
let cast_expr = match self.parse_ty_no_plus() {
685+
let cast_expr = match self.parse_as_cast_ty() {
686686
Ok(rhs) => mk_expr(self, lhs, rhs),
687687
Err(mut type_err) => {
688688
// Rewind to before attempting to parse the type with generics, to recover
@@ -808,7 +808,7 @@ impl<'a> Parser<'a> {
808808
"casts cannot be followed by {}",
809809
match with_postfix.kind {
810810
ExprKind::Index(_, _) => "indexing",
811-
ExprKind::Try(_) => "?",
811+
ExprKind::Try(_) => "`?`",
812812
ExprKind::Field(_, _) => "a field access",
813813
ExprKind::MethodCall(_, _, _) => "a method call",
814814
ExprKind::Call(_, _) => "a function call",

0 commit comments

Comments
 (0)