Skip to content

Commit 3d68afc

Browse files
committed
Auto merge of rust-lang#127936 - matthiaskrgr:rollup-ci0eg7k, r=tgross35
Rollup of 8 pull requests Successful merges: - rust-lang#127418 (Wrap too long type name) - rust-lang#127594 (Fuchsia status code match arm) - rust-lang#127835 (Fix ICE in suggestion caused by `⩵` being recovered as `==`) - rust-lang#127858 (match lowering: Rename `MatchPair` to `MatchPairTree`) - rust-lang#127871 (Mention that type parameters are used recursively on bivariance error) - rust-lang#127913 (remove `debug-logging` default from tools profile) - rust-lang#127925 (Remove tag field from `Relation`s) - rust-lang#127929 (Use more accurate span for `addr_of!` suggestion) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5affbb1 + d1250bc commit 3d68afc

File tree

63 files changed

+447
-247
lines changed

Some content is hidden

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

63 files changed

+447
-247
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

-4
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,6 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
313313
self.type_checker.infcx.tcx
314314
}
315315

316-
fn tag(&self) -> &'static str {
317-
"nll::subtype"
318-
}
319-
320316
#[instrument(skip(self, info), level = "trace", ret)]
321317
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
322318
&mut self,

compiler/rustc_hir_analysis/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no
382382
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
383383
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
384384
385+
hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively
386+
.label = {$param_def_kind} must be used non-recursively in the definition
387+
.note = all type parameters must be used in a non-recursive way in order to constrain their variance
388+
385389
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
386390
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
387391
@@ -549,6 +553,8 @@ hir_analysis_unused_generic_parameter =
549553
{$param_def_kind} `{$param_name}` is never used
550554
.label = unused {$param_def_kind}
551555
.const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead
556+
.usage_spans = `{$param_name}` is named here, but is likely unused in the containing type
557+
552558
hir_analysis_unused_generic_parameter_adt_help =
553559
consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`
554560
hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =

compiler/rustc_hir_analysis/src/check/check.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
15721572
param_name,
15731573
param_def_kind: tcx.def_descr(param.def_id),
15741574
help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
1575+
usage_spans: vec![],
15751576
const_param_help,
15761577
});
15771578
diag.code(E0091);

compiler/rustc_hir_analysis/src/check/errs.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use rustc_hir as hir;
2-
use rustc_hir_pretty::qpath_to_string;
32
use rustc_lint_defs::builtin::STATIC_MUT_REFS;
43
use rustc_middle::ty::{Mutability, TyCtxt};
54
use rustc_span::Span;
@@ -12,9 +11,17 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
1211
let hir_id = expr.hir_id;
1312
if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
1413
&& matches!(borrow_kind, hir::BorrowKind::Ref)
15-
&& let Some(var) = path_if_static_mut(tcx, expr)
14+
&& path_if_static_mut(expr)
1615
{
17-
handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
16+
handle_static_mut_ref(
17+
tcx,
18+
span,
19+
span.with_hi(expr.span.lo()),
20+
span.shrink_to_hi(),
21+
span.edition().at_least_rust_2024(),
22+
m,
23+
hir_id,
24+
);
1825
}
1926
}
2027

@@ -24,51 +31,53 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
2431
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
2532
&& let hir::ByRef::Yes(rmutbl) = ba.0
2633
&& let Some(init) = loc.init
27-
&& let Some(var) = path_if_static_mut(tcx, init)
34+
&& path_if_static_mut(init)
2835
{
2936
handle_static_mut_ref(
3037
tcx,
3138
init.span,
32-
var,
39+
init.span.shrink_to_lo(),
40+
init.span.shrink_to_hi(),
3341
loc.span.edition().at_least_rust_2024(),
3442
rmutbl,
3543
stmt.hir_id,
3644
);
3745
}
3846
}
3947

40-
fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
48+
fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool {
4149
if let hir::ExprKind::Path(qpath) = expr.kind
4250
&& let hir::QPath::Resolved(_, path) = qpath
4351
&& let hir::def::Res::Def(def_kind, _) = path.res
4452
&& let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
4553
def_kind
4654
{
47-
return Some(qpath_to_string(&tcx, &qpath));
55+
return true;
4856
}
49-
None
57+
false
5058
}
5159

5260
fn handle_static_mut_ref(
5361
tcx: TyCtxt<'_>,
5462
span: Span,
55-
var: String,
63+
lo: Span,
64+
hi: Span,
5665
e2024: bool,
5766
mutable: Mutability,
5867
hir_id: hir::HirId,
5968
) {
6069
if e2024 {
6170
let (sugg, shared) = if mutable == Mutability::Mut {
62-
(errors::StaticMutRefSugg::Mut { span, var }, "mutable")
71+
(errors::MutRefSugg::Mut { lo, hi }, "mutable")
6372
} else {
64-
(errors::StaticMutRefSugg::Shared { span, var }, "shared")
73+
(errors::MutRefSugg::Shared { lo, hi }, "shared")
6574
};
6675
tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared });
6776
} else {
6877
let (sugg, shared) = if mutable == Mutability::Mut {
69-
(errors::RefOfMutStaticSugg::Mut { span, var }, "mutable")
78+
(errors::MutRefSugg::Mut { lo, hi }, "mutable")
7079
} else {
71-
(errors::RefOfMutStaticSugg::Shared { span, var }, "shared")
80+
(errors::MutRefSugg::Shared { lo, hi }, "shared")
7281
};
7382
tcx.emit_node_span_lint(
7483
STATIC_MUT_REFS,

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+124-9
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
44
use crate::errors;
55
use crate::fluent_generated as fluent;
66

7-
use hir::intravisit::Visitor;
7+
use hir::intravisit::{self, Visitor};
88
use rustc_ast as ast;
99
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
1010
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
1111
use rustc_hir as hir;
12-
use rustc_hir::def::DefKind;
12+
use rustc_hir::def::{DefKind, Res};
1313
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1414
use rustc_hir::lang_items::LangItem;
1515
use rustc_hir::ItemKind;
@@ -1799,7 +1799,7 @@ fn receiver_is_implemented<'tcx>(
17991799

18001800
fn check_variances_for_type_defn<'tcx>(
18011801
tcx: TyCtxt<'tcx>,
1802-
item: &hir::Item<'tcx>,
1802+
item: &'tcx hir::Item<'tcx>,
18031803
hir_generics: &hir::Generics<'tcx>,
18041804
) {
18051805
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
@@ -1886,21 +1886,21 @@ fn check_variances_for_type_defn<'tcx>(
18861886
hir::ParamName::Error => {}
18871887
_ => {
18881888
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
1889-
report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind);
1889+
report_bivariance(tcx, hir_param, has_explicit_bounds, item);
18901890
}
18911891
}
18921892
}
18931893
}
18941894

1895-
fn report_bivariance(
1896-
tcx: TyCtxt<'_>,
1897-
param: &rustc_hir::GenericParam<'_>,
1895+
fn report_bivariance<'tcx>(
1896+
tcx: TyCtxt<'tcx>,
1897+
param: &'tcx hir::GenericParam<'tcx>,
18981898
has_explicit_bounds: bool,
1899-
item_kind: ItemKind<'_>,
1899+
item: &'tcx hir::Item<'tcx>,
19001900
) -> ErrorGuaranteed {
19011901
let param_name = param.name.ident();
19021902

1903-
let help = match item_kind {
1903+
let help = match item.kind {
19041904
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
19051905
if let Some(def_id) = tcx.lang_items().phantom_data() {
19061906
errors::UnusedGenericParameterHelp::Adt {
@@ -1915,6 +1915,49 @@ fn report_bivariance(
19151915
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
19161916
};
19171917

1918+
let mut usage_spans = vec![];
1919+
intravisit::walk_item(
1920+
&mut CollectUsageSpans { spans: &mut usage_spans, param_def_id: param.def_id.to_def_id() },
1921+
item,
1922+
);
1923+
1924+
if !usage_spans.is_empty() {
1925+
// First, check if the ADT is (probably) cyclical. We say probably here, since
1926+
// we're not actually looking into substitutions, just walking through fields.
1927+
// And we only recurse into the fields of ADTs, and not the hidden types of
1928+
// opaques or anything else fancy.
1929+
let item_def_id = item.owner_id.to_def_id();
1930+
let is_probably_cyclical = if matches!(
1931+
tcx.def_kind(item_def_id),
1932+
DefKind::Struct | DefKind::Union | DefKind::Enum
1933+
) {
1934+
IsProbablyCyclical { tcx, adt_def_id: item_def_id, seen: Default::default() }
1935+
.visit_all_fields(tcx.adt_def(item_def_id))
1936+
.is_break()
1937+
} else {
1938+
false
1939+
};
1940+
// If the ADT is cyclical, then if at least one usage of the type parameter or
1941+
// the `Self` alias is present in the, then it's probably a cyclical struct, and
1942+
// we should call those parameter usages recursive rather than just saying they're
1943+
// unused...
1944+
//
1945+
// We currently report *all* of the parameter usages, since computing the exact
1946+
// subset is very involved, and the fact we're mentioning recursion at all is
1947+
// likely to guide the user in the right direction.
1948+
if is_probably_cyclical {
1949+
let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter {
1950+
spans: usage_spans,
1951+
param_span: param.span,
1952+
param_name,
1953+
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
1954+
help,
1955+
note: (),
1956+
});
1957+
return diag.emit();
1958+
}
1959+
}
1960+
19181961
let const_param_help =
19191962
matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
19201963
.then_some(());
@@ -1923,13 +1966,85 @@ fn report_bivariance(
19231966
span: param.span,
19241967
param_name,
19251968
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
1969+
usage_spans,
19261970
help,
19271971
const_param_help,
19281972
});
19291973
diag.code(E0392);
19301974
diag.emit()
19311975
}
19321976

1977+
/// Detects cases where an ADT is trivially cyclical -- we want to detect this so
1978+
/// /we only mention that its parameters are used cyclically if the ADT is truly
1979+
/// cyclical.
1980+
///
1981+
/// Notably, we don't consider substitutions here, so this may have false positives.
1982+
struct IsProbablyCyclical<'tcx> {
1983+
tcx: TyCtxt<'tcx>,
1984+
adt_def_id: DefId,
1985+
seen: FxHashSet<DefId>,
1986+
}
1987+
1988+
impl<'tcx> IsProbablyCyclical<'tcx> {
1989+
fn visit_all_fields(&mut self, adt_def: ty::AdtDef<'tcx>) -> ControlFlow<(), ()> {
1990+
for field in adt_def.all_fields() {
1991+
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
1992+
}
1993+
1994+
ControlFlow::Continue(())
1995+
}
1996+
}
1997+
1998+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
1999+
type Result = ControlFlow<(), ()>;
2000+
2001+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
2002+
if let Some(adt_def) = t.ty_adt_def() {
2003+
if adt_def.did() == self.adt_def_id {
2004+
return ControlFlow::Break(());
2005+
}
2006+
2007+
if self.seen.insert(adt_def.did()) {
2008+
self.visit_all_fields(adt_def)?;
2009+
}
2010+
}
2011+
2012+
t.super_visit_with(self)
2013+
}
2014+
}
2015+
2016+
/// Collect usages of the `param_def_id` and `Res::SelfTyAlias` in the HIR.
2017+
///
2018+
/// This is used to report places where the user has used parameters in a
2019+
/// non-variance-constraining way for better bivariance errors.
2020+
struct CollectUsageSpans<'a> {
2021+
spans: &'a mut Vec<Span>,
2022+
param_def_id: DefId,
2023+
}
2024+
2025+
impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> {
2026+
type Result = ();
2027+
2028+
fn visit_generics(&mut self, _g: &'tcx rustc_hir::Generics<'tcx>) -> Self::Result {
2029+
// Skip the generics. We only care about fields, not where clause/param bounds.
2030+
}
2031+
2032+
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
2033+
if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind {
2034+
if let Res::Def(DefKind::TyParam, def_id) = qpath.res
2035+
&& def_id == self.param_def_id
2036+
{
2037+
self.spans.push(t.span);
2038+
return;
2039+
} else if let Res::SelfTyAlias { .. } = qpath.res {
2040+
self.spans.push(t.span);
2041+
return;
2042+
}
2043+
}
2044+
intravisit::walk_ty(self, t);
2045+
}
2046+
}
2047+
19332048
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
19342049
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
19352050
/// aren't true.

0 commit comments

Comments
 (0)