Skip to content

Commit 2d8651a

Browse files
committed
Auto merge of #106034 - matthiaskrgr:rollup-2zpql33, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #104741 (Switch `#[track_caller]` back to a no-op unless feature gate is enabled) - #105769 (add function to tell the identical errors for ambiguity_errors) - #105843 (Suggest associated const on possible capitalization mistake) - #105966 (Re-enable `Fn` trait call notation error for non-tuple argument) - #106002 (codegen tests: adapt patterns to also work with v0 symbol mangling) - #106010 (Give opaque types a better coherence error) - #106016 (rustdoc: simplify link anchor to section expand JS) - #106024 (Fix ICE due to `todo!()` in `rustdoc` for `Term`s) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents cce9e72 + d2130e4 commit 2d8651a

File tree

28 files changed

+414
-126
lines changed

28 files changed

+414
-126
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
656656
hir::ExprKind::Closure(c)
657657
};
658658

659-
let track_caller = self
660-
.attrs
661-
.get(&outer_hir_id.local_id)
662-
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
663-
664659
let hir_id = self.lower_node_id(closure_node_id);
665-
if track_caller {
666-
let unstable_span = self.mark_span_with_reason(
667-
DesugaringKind::Async,
668-
span,
669-
self.allow_gen_future.clone(),
670-
);
660+
let unstable_span =
661+
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
662+
663+
if self.tcx.features().closure_track_caller
664+
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
665+
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
666+
{
671667
self.lower_attrs(
672668
hir_id,
673669
&[Attribute {

compiler/rustc_error_messages/locales/en-US/lint.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes =
350350
351351
lint_builtin_unstable_features = unstable feature
352352
353+
lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
354+
.label = this function will not propagate the caller location
355+
353356
lint_builtin_unreachable_pub = unreachable `pub` {$what}
354357
.suggestion = consider restricting its visibility
355358
.help = or consider exporting it for use by other crates

compiler/rustc_hir_analysis/src/coherence/orphan.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,19 @@ fn emit_orphan_check_error<'tcx>(
184184
ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
185185
_ => ty,
186186
};
187-
let this = "this".to_string();
188-
let (ty, postfix) = match &ty.kind() {
189-
ty::Slice(_) => (this, " because slices are always foreign"),
190-
ty::Array(..) => (this, " because arrays are always foreign"),
191-
ty::Tuple(..) => (this, " because tuples are always foreign"),
187+
let msg = |ty: &str, postfix: &str| {
188+
format!("{ty} is not defined in the current crate{postfix}")
189+
};
190+
let this = |name: &str| msg("this", &format!(" because {name} are always foreign"));
191+
let msg = match &ty.kind() {
192+
ty::Slice(_) => this("slices"),
193+
ty::Array(..) => this("arrays"),
194+
ty::Tuple(..) => this("tuples"),
195+
ty::Alias(ty::Opaque, ..) => {
196+
"type alias impl trait is treated as if it were foreign, \
197+
because its hidden type could be from a foreign crate"
198+
.to_string()
199+
}
192200
ty::RawPtr(ptr_ty) => {
193201
emit_newtype_suggestion_for_raw_ptr(
194202
full_impl_span,
@@ -198,12 +206,11 @@ fn emit_orphan_check_error<'tcx>(
198206
&mut err,
199207
);
200208

201-
(format!("`{}`", ty), " because raw pointers are always foreign")
209+
msg(&format!("`{ty}`"), " because raw pointers are always foreign")
202210
}
203-
_ => (format!("`{}`", ty), ""),
211+
_ => msg(&format!("`{ty}`"), ""),
204212
};
205213

206-
let msg = format!("{} is not defined in the current crate{}", ty, postfix);
207214
if is_target_ty {
208215
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
209216
err.span_label(self_ty_span, &msg);

compiler/rustc_hir_typeck/src/demand.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,24 @@ use std::cmp::min;
2323
use std::iter;
2424

2525
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26-
pub fn emit_coerce_suggestions(
26+
pub fn emit_type_mismatch_suggestions(
2727
&self,
2828
err: &mut Diagnostic,
2929
expr: &hir::Expr<'tcx>,
3030
expr_ty: Ty<'tcx>,
3131
expected: Ty<'tcx>,
3232
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
33-
error: Option<TypeError<'tcx>>,
33+
_error: Option<TypeError<'tcx>>,
3434
) {
3535
if expr_ty == expected {
3636
return;
3737
}
3838

39-
self.annotate_expected_due_to_let_ty(err, expr, error);
40-
4139
// Use `||` to give these suggestions a precedence
4240
let _ = self.suggest_missing_parentheses(err, expr)
41+
|| self.suggest_associated_const(err, expr, expected)
4342
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
43+
|| self.suggest_option_to_bool(err, expr, expr_ty, expected)
4444
|| self.suggest_compatible_variants(err, expr, expected, expr_ty)
4545
|| self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
4646
|| self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
@@ -49,9 +49,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4949
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
5050
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
5151
|| self.suggest_into(err, expr, expr_ty, expected)
52-
|| self.suggest_option_to_bool(err, expr, expr_ty, expected)
5352
|| self.suggest_floating_point_literal(err, expr, expected);
53+
}
5454

55+
pub fn emit_coerce_suggestions(
56+
&self,
57+
err: &mut Diagnostic,
58+
expr: &hir::Expr<'tcx>,
59+
expr_ty: Ty<'tcx>,
60+
expected: Ty<'tcx>,
61+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
62+
error: Option<TypeError<'tcx>>,
63+
) {
64+
if expr_ty == expected {
65+
return;
66+
}
67+
68+
self.annotate_expected_due_to_let_ty(err, expr, error);
69+
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
5570
self.note_type_is_not_clone(err, expected, expr_ty, expr);
5671
self.note_need_for_fn_pointer(err, expected, expr_ty);
5772
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);

compiler/rustc_hir_typeck/src/expr.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
104104
}
105105

106106
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
107-
// FIXME(compiler-errors): We probably should fold some of the
108-
// `suggest_` functions from `emit_coerce_suggestions` into here,
109-
// since some of those aren't necessarily just coerce suggestions.
110-
let _ = self.suggest_deref_ref_or_into(
107+
let _ = self.emit_type_mismatch_suggestions(
111108
&mut err,
112109
expr.peel_drop_temps(),
113-
expected_ty,
114110
ty,
111+
expected_ty,
115112
None,
116-
) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty);
113+
None,
114+
);
117115
extend_err(&mut err);
118116
err.emit();
119117
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
214214
"cannot use call notation; the first type parameter \
215215
for the function trait is neither a tuple nor unit"
216216
)
217-
.delay_as_bug();
217+
.emit();
218218
(self.err_args(provided_args.len()), None)
219219
}
220220
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+82-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::FnCtxt;
22

33
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
4+
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
45
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
56
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
67
use rustc_hir as hir;
@@ -15,10 +16,11 @@ use rustc_infer::traits::{self, StatementAsExpression};
1516
use rustc_middle::lint::in_external_macro;
1617
use rustc_middle::ty::{
1718
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
19+
TypeVisitable,
1820
};
1921
use rustc_session::errors::ExprParenthesesNeeded;
20-
use rustc_span::symbol::sym;
21-
use rustc_span::Span;
22+
use rustc_span::symbol::{sym, Ident};
23+
use rustc_span::{Span, Symbol};
2224
use rustc_trait_selection::infer::InferCtxtExt;
2325
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
2426
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -1236,6 +1238,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12361238
}
12371239
}
12381240

1241+
pub(crate) fn suggest_associated_const(
1242+
&self,
1243+
err: &mut Diagnostic,
1244+
expr: &hir::Expr<'_>,
1245+
expected_ty: Ty<'tcx>,
1246+
) -> bool {
1247+
let Some((DefKind::AssocFn, old_def_id)) = self.typeck_results.borrow().type_dependent_def(expr.hir_id) else {
1248+
return false;
1249+
};
1250+
let old_item_name = self.tcx.item_name(old_def_id);
1251+
let capitalized_name = Symbol::intern(&old_item_name.as_str().to_uppercase());
1252+
if old_item_name == capitalized_name {
1253+
return false;
1254+
}
1255+
let (item, segment) = match expr.kind {
1256+
hir::ExprKind::Path(QPath::Resolved(
1257+
Some(ty),
1258+
hir::Path { segments: [segment], .. },
1259+
))
1260+
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
1261+
let self_ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
1262+
if let Ok(pick) = self.probe_for_name(
1263+
Mode::Path,
1264+
Ident::new(capitalized_name, segment.ident.span),
1265+
IsSuggestion(true),
1266+
self_ty,
1267+
expr.hir_id,
1268+
ProbeScope::TraitsInScope,
1269+
) {
1270+
(pick.item, segment)
1271+
} else {
1272+
return false;
1273+
}
1274+
}
1275+
hir::ExprKind::Path(QPath::Resolved(
1276+
None,
1277+
hir::Path { segments: [.., segment], .. },
1278+
)) => {
1279+
// we resolved through some path that doesn't end in the item name,
1280+
// better not do a bad suggestion by accident.
1281+
if old_item_name != segment.ident.name {
1282+
return false;
1283+
}
1284+
if let Some(item) = self
1285+
.tcx
1286+
.associated_items(self.tcx.parent(old_def_id))
1287+
.filter_by_name_unhygienic(capitalized_name)
1288+
.next()
1289+
{
1290+
(*item, segment)
1291+
} else {
1292+
return false;
1293+
}
1294+
}
1295+
_ => return false,
1296+
};
1297+
if item.def_id == old_def_id || self.tcx.def_kind(item.def_id) != DefKind::AssocConst {
1298+
// Same item
1299+
return false;
1300+
}
1301+
let item_ty = self.tcx.type_of(item.def_id);
1302+
// FIXME(compiler-errors): This check is *so* rudimentary
1303+
if item_ty.needs_subst() {
1304+
return false;
1305+
}
1306+
if self.can_coerce(item_ty, expected_ty) {
1307+
err.span_suggestion_verbose(
1308+
segment.ident.span,
1309+
format!("try referring to the associated const `{capitalized_name}` instead",),
1310+
capitalized_name,
1311+
Applicability::MachineApplicable,
1312+
);
1313+
true
1314+
} else {
1315+
false
1316+
}
1317+
}
1318+
12391319
fn is_loop(&self, id: hir::HirId) -> bool {
12401320
let node = self.tcx.hir().get(id);
12411321
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))

compiler/rustc_lint/src/builtin.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::{
2525
types::{transparent_newtype_field, CItemKind},
2626
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
2727
};
28+
use hir::IsAsync;
2829
use rustc_ast::attr;
2930
use rustc_ast::tokenstream::{TokenStream, TokenTree};
3031
use rustc_ast::visit::{FnCtxt, FnKind};
@@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
4041
use rustc_hir as hir;
4142
use rustc_hir::def::{DefKind, Res};
4243
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
43-
use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin};
44+
use rustc_hir::intravisit::FnKind as HirFnKind;
45+
use rustc_hir::{
46+
Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
47+
};
4448
use rustc_index::vec::Idx;
4549
use rustc_middle::lint::in_external_macro;
4650
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@@ -1370,6 +1374,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
13701374
}
13711375
}
13721376

1377+
declare_lint! {
1378+
/// The `ungated_async_fn_track_caller` lint warns when the
1379+
/// `#[track_caller]` attribute is used on an async function, method, or
1380+
/// closure, without enabling the corresponding unstable feature flag.
1381+
///
1382+
/// ### Example
1383+
///
1384+
/// ```rust
1385+
/// #[track_caller]
1386+
/// async fn foo() {}
1387+
/// ```
1388+
///
1389+
/// {{produces}}
1390+
///
1391+
/// ### Explanation
1392+
///
1393+
/// The attribute must be used in conjunction with the
1394+
/// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
1395+
/// annotation will function as as no-op.
1396+
///
1397+
/// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
1398+
UNGATED_ASYNC_FN_TRACK_CALLER,
1399+
Warn,
1400+
"enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
1401+
}
1402+
1403+
declare_lint_pass!(
1404+
/// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
1405+
/// do anything
1406+
UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
1407+
);
1408+
1409+
impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
1410+
fn check_fn(
1411+
&mut self,
1412+
cx: &LateContext<'_>,
1413+
fn_kind: HirFnKind<'_>,
1414+
_: &'tcx FnDecl<'_>,
1415+
_: &'tcx Body<'_>,
1416+
span: Span,
1417+
hir_id: HirId,
1418+
) {
1419+
if fn_kind.asyncness() == IsAsync::Async
1420+
&& !cx.tcx.features().closure_track_caller
1421+
&& let attrs = cx.tcx.hir().attrs(hir_id)
1422+
// Now, check if the function has the `#[track_caller]` attribute
1423+
&& let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
1424+
{
1425+
cx.struct_span_lint(
1426+
UNGATED_ASYNC_FN_TRACK_CALLER,
1427+
attr.span,
1428+
fluent::lint_ungated_async_fn_track_caller,
1429+
|lint| {
1430+
lint.span_label(span, fluent::label);
1431+
rustc_session::parse::add_feature_diagnostics(
1432+
lint,
1433+
&cx.tcx.sess.parse_sess,
1434+
sym::closure_track_caller,
1435+
);
1436+
lint
1437+
},
1438+
);
1439+
}
1440+
}
1441+
}
1442+
13731443
declare_lint! {
13741444
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
13751445
/// the crate root.

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ late_lint_methods!(
219219
// May Depend on constants elsewhere
220220
UnusedBrokenConst: UnusedBrokenConst,
221221
UnstableFeatures: UnstableFeatures,
222+
UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
222223
ArrayIntoIter: ArrayIntoIter::default(),
223224
DropTraitConstraints: DropTraitConstraints,
224225
TemporaryCStringAsPtr: TemporaryCStringAsPtr,

0 commit comments

Comments
 (0)