Skip to content

Commit a3ceeeb

Browse files
committed
Auto merge of #152200 - jieyouxu:rollup-UNFpgZy, r=jieyouxu
Rollup of 4 pull requests Successful merges: - #152174 (stdarch subtree update) - #151278 (Provide more context on trait bounds being unmet due to imperfect derive) - #151955 (escape symbol names in global asm) - #152194 (Remove the 4 failing tests from rustdoc-gui) Failed merges: - #152191 (Convert to inline diagnostics in `rustc_hir_analysis`)
2 parents f889772 + 7afff45 commit a3ceeeb

File tree

104 files changed

+1887
-2646
lines changed

Some content is hidden

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

104 files changed

+1887
-2646
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12561256
self.suggest_cloning_inner(err, ty, expr);
12571257
}
12581258
} else if let ty::Adt(def, args) = ty.kind()
1259-
&& def.did().as_local().is_some()
1259+
&& let Some(local_did) = def.did().as_local()
12601260
&& def.variants().iter().all(|variant| {
12611261
variant
12621262
.fields
@@ -1266,12 +1266,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12661266
{
12671267
let ty_span = self.infcx.tcx.def_span(def.did());
12681268
let mut span: MultiSpan = ty_span.into();
1269-
span.push_span_label(ty_span, "consider implementing `Clone` for this type");
1270-
span.push_span_label(expr.span, "you could clone this value");
1271-
err.span_note(
1272-
span,
1273-
format!("if `{ty}` implemented `Clone`, you could clone the value"),
1269+
let mut derive_clone = false;
1270+
self.infcx.tcx.for_each_relevant_impl(
1271+
self.infcx.tcx.lang_items().clone_trait().unwrap(),
1272+
ty,
1273+
|def_id| {
1274+
if self.infcx.tcx.is_automatically_derived(def_id) {
1275+
derive_clone = true;
1276+
span.push_span_label(
1277+
self.infcx.tcx.def_span(def_id),
1278+
"derived `Clone` adds implicit bounds on type parameters",
1279+
);
1280+
if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) {
1281+
for param in generics.params {
1282+
if let hir::GenericParamKind::Type { .. } = param.kind {
1283+
span.push_span_label(
1284+
param.span,
1285+
format!(
1286+
"introduces an implicit `{}: Clone` bound",
1287+
param.name.ident()
1288+
),
1289+
);
1290+
}
1291+
}
1292+
}
1293+
}
1294+
},
12741295
);
1296+
let msg = if !derive_clone {
1297+
span.push_span_label(
1298+
ty_span,
1299+
format!(
1300+
"consider {}implementing `Clone` for this type",
1301+
if derive_clone { "manually " } else { "" }
1302+
),
1303+
);
1304+
format!("if `{ty}` implemented `Clone`, you could clone the value")
1305+
} else {
1306+
format!("if all bounds were met, you could clone the value")
1307+
};
1308+
span.push_span_label(expr.span, "you could clone this value");
1309+
err.span_note(span, msg);
1310+
if derive_clone {
1311+
err.help("consider manually implementing `Clone` to avoid undesired bounds");
1312+
}
12751313
} else if let ty::Param(param) = ty.kind()
12761314
&& let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
12771315
&& let generics = self.infcx.tcx.generics_of(self.mir_def_id())

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -638,27 +638,27 @@ impl<'a> TraitDef<'a> {
638638
GenericParamKind::Type { .. } => {
639639
// Extra restrictions on the generics parameters to the
640640
// type being derived upon.
641+
let span = param.ident.span.with_ctxt(ctxt);
641642
let bounds: Vec<_> = self
642643
.additional_bounds
643644
.iter()
644645
.map(|p| {
645-
cx.trait_bound(
646-
p.to_path(cx, self.span, type_ident, generics),
647-
self.is_const,
648-
)
646+
cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const)
649647
})
650648
.chain(
651649
// Add a bound for the current trait.
652-
self.skip_path_as_bound
653-
.not()
654-
.then(|| cx.trait_bound(trait_path.clone(), self.is_const)),
650+
self.skip_path_as_bound.not().then(|| {
651+
let mut trait_path = trait_path.clone();
652+
trait_path.span = span;
653+
cx.trait_bound(trait_path, self.is_const)
654+
}),
655655
)
656656
.chain({
657657
// Add a `Copy` bound if required.
658658
if is_packed && self.needs_copy_as_bound_if_packed {
659659
let p = deriving::path_std!(marker::Copy);
660660
Some(cx.trait_bound(
661-
p.to_path(cx, self.span, type_ident, generics),
661+
p.to_path(cx, span, type_ident, generics),
662662
self.is_const,
663663
))
664664
} else {
@@ -671,7 +671,7 @@ impl<'a> TraitDef<'a> {
671671
)
672672
.collect();
673673

674-
cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
674+
cx.typaram(span, param.ident, bounds, None)
675675
}
676676
GenericParamKind::Const { ty, span, .. } => {
677677
let const_nodefault_kind = GenericParamKind::Const {
@@ -791,7 +791,8 @@ impl<'a> TraitDef<'a> {
791791
.collect();
792792

793793
// Create the type of `self`.
794-
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
794+
let path =
795+
cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params);
795796
let self_type = cx.ty_path(path);
796797
let rustc_const_unstable =
797798
cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
399399
for piece in template {
400400
match *piece {
401401
InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s),
402-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
402+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
403403
match operands[operand_idx] {
404404
GlobalAsmOperandRef::Const { ref string } => {
405405
// Const operands get injected directly into the
@@ -414,7 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
414414
llvm::LLVMRustGetMangledName(llval, s);
415415
})
416416
.expect("symbol is not valid UTF-8");
417-
template_str.push_str(&symbol);
417+
template_str.push_str(&escape_symbol_name(self, symbol, span));
418418
}
419419
GlobalAsmOperandRef::SymStatic { def_id } => {
420420
let llval = self
@@ -428,7 +428,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
428428
llvm::LLVMRustGetMangledName(llval, s);
429429
})
430430
.expect("symbol is not valid UTF-8");
431-
template_str.push_str(&symbol);
431+
template_str.push_str(&escape_symbol_name(self, symbol, span));
432432
}
433433
}
434434
}
@@ -1390,3 +1390,42 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
13901390
_ => layout.llvm_type(cx),
13911391
}
13921392
}
1393+
1394+
fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String {
1395+
use rustc_target::spec::{Arch, BinaryFormat};
1396+
if !symbol.is_empty()
1397+
&& symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.'))
1398+
{
1399+
return symbol;
1400+
}
1401+
if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff {
1402+
cx.tcx.sess.dcx().span_fatal(
1403+
span,
1404+
format!(
1405+
"symbol escaping is not supported for the binary format {}",
1406+
cx.tcx.sess.target.binary_format
1407+
),
1408+
);
1409+
}
1410+
if cx.tcx.sess.target.arch == Arch::Nvptx64 {
1411+
cx.tcx.sess.dcx().span_fatal(
1412+
span,
1413+
format!(
1414+
"symbol escaping is not supported for the architecture {}",
1415+
cx.tcx.sess.target.arch
1416+
),
1417+
);
1418+
}
1419+
let mut escaped_symbol = String::new();
1420+
escaped_symbol.push('\"');
1421+
for c in symbol.chars() {
1422+
match c {
1423+
'\n' => escaped_symbol.push_str("\\\n"),
1424+
'"' => escaped_symbol.push_str("\\\""),
1425+
'\\' => escaped_symbol.push_str("\\\\"),
1426+
c => escaped_symbol.push(c),
1427+
}
1428+
}
1429+
escaped_symbol.push('\"');
1430+
escaped_symbol
1431+
}

compiler/rustc_hir/src/hir.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// ignore-tidy-filelength
22
use std::borrow::Cow;
33
use std::fmt;
4+
use std::ops::Not;
45

56
use rustc_abi::ExternAbi;
67
use rustc_ast::attr::AttributeExt;
@@ -1012,10 +1013,14 @@ impl<'hir> Generics<'hir> {
10121013

10131014
span_for_parentheses.map_or_else(
10141015
|| {
1015-
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
1016-
// as we use this method to get a span appropriate for suggestions.
1016+
// We include bounds that come from a `#[derive(_)]` but point at the user's
1017+
// code, as we use this method to get a span appropriate for suggestions.
10171018
let bs = bound.span();
1018-
bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None))
1019+
// We use `from_expansion` instead of `can_be_used_for_suggestions` because
1020+
// the trait bound from imperfect derives do point at the type parameter,
1021+
// but expanded to a where clause, so we want to ignore those. This is only
1022+
// true for derive intrinsics.
1023+
bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None))
10191024
},
10201025
|span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))),
10211026
)

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt =
142142
hir_analysis_copy_impl_on_type_with_dtor =
143143
the trait `Copy` cannot be implemented for this type; the type has a destructor
144144
.label = `Copy` not allowed on types with destructors
145+
.note = destructor declared here
145146
146147
hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`
147148
.label = can't implement cross-crate trait with a default impl for non-struct/enum type

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
122122
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
123123
Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
124124
}
125-
Err(CopyImplementationError::HasDestructor) => {
125+
Err(CopyImplementationError::HasDestructor(did)) => {
126126
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
127-
Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
127+
let impl_ = tcx.def_span(did);
128+
Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ }))
128129
}
129130
Err(CopyImplementationError::HasUnsafeFields) => {
130131
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor {
278278
#[primary_span]
279279
#[label]
280280
pub span: Span,
281+
#[note]
282+
pub impl_: Span,
281283
}
282284

283285
#[derive(Diagnostic)]

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
592592
if span.can_be_used_for_suggestions()
593593
&& poly_trait_ref.trait_ref.trait_def_id().is_some()
594594
&& !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag)
595-
&& !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag)
595+
&& !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag)
596596
{
597597
self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag);
598598
}
@@ -750,10 +750,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
750750
fn maybe_suggest_dyn_trait(
751751
&self,
752752
hir_id: hir::HirId,
753+
span: Span,
753754
sugg: Vec<(Span, String)>,
754755
diag: &mut Diag<'_>,
755756
) -> bool {
756757
let tcx = self.tcx();
758+
if span.in_derive_expansion() {
759+
return false;
760+
}
757761

758762
// Look at the direct HIR parent, since we care about the relationship between
759763
// the type and the thing that directly encloses it.

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,25 +1932,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19321932
None,
19331933
);
19341934
} else {
1935+
let mut suggest_derive = true;
19351936
if let Some(errors) =
19361937
self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env)
19371938
{
1939+
let manually_impl = "consider manually implementing `Clone` to avoid the \
1940+
implicit type parameter bounds";
19381941
match &errors[..] {
19391942
[] => {}
19401943
[error] => {
1941-
diag.help(format!(
1942-
"`Clone` is not implemented because the trait bound `{}` is \
1943-
not satisfied",
1944-
error.obligation.predicate,
1945-
));
1944+
let msg = "`Clone` is not implemented because a trait bound is not \
1945+
satisfied";
1946+
if let traits::ObligationCauseCode::ImplDerived(data) =
1947+
error.obligation.cause.code()
1948+
{
1949+
let mut span: MultiSpan = data.span.into();
1950+
if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) {
1951+
span.push_span_label(
1952+
data.span,
1953+
format!(
1954+
"derive introduces an implicit `{}` bound",
1955+
error.obligation.predicate
1956+
),
1957+
);
1958+
}
1959+
diag.span_help(span, msg);
1960+
if self.tcx.is_automatically_derived(data.impl_or_alias_def_id)
1961+
&& data.impl_or_alias_def_id.is_local()
1962+
{
1963+
diag.help(manually_impl);
1964+
suggest_derive = false;
1965+
}
1966+
} else {
1967+
diag.help(msg);
1968+
}
19461969
}
19471970
_ => {
1948-
diag.help(format!(
1949-
"`Clone` is not implemented because the following trait bounds \
1950-
could not be satisfied: {}",
1951-
listify(&errors, |e| format!("`{}`", e.obligation.predicate))
1952-
.unwrap(),
1953-
));
1971+
let unsatisfied_bounds: Vec<_> = errors
1972+
.iter()
1973+
.filter_map(|error| match error.obligation.cause.code() {
1974+
traits::ObligationCauseCode::ImplDerived(data) => {
1975+
let pre = if self
1976+
.tcx
1977+
.is_automatically_derived(data.impl_or_alias_def_id)
1978+
{
1979+
"derive introduces an implicit "
1980+
} else {
1981+
""
1982+
};
1983+
Some((
1984+
data.span,
1985+
format!(
1986+
"{pre}unsatisfied trait bound `{}`",
1987+
error.obligation.predicate
1988+
),
1989+
))
1990+
}
1991+
_ => None,
1992+
})
1993+
.collect();
1994+
let msg = "`Clone` is not implemented because the some trait bounds \
1995+
could not be satisfied";
1996+
if errors.len() == unsatisfied_bounds.len() {
1997+
let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds
1998+
.iter()
1999+
.map(|(span, _)| *span)
2000+
.collect::<Vec<Span>>()
2001+
.into();
2002+
for (span, label) in unsatisfied_bounds {
2003+
unsatisfied_bounds_spans.push_span_label(span, label);
2004+
}
2005+
diag.span_help(unsatisfied_bounds_spans, msg);
2006+
if errors.iter().all(|error| match error.obligation.cause.code() {
2007+
traits::ObligationCauseCode::ImplDerived(data) => {
2008+
self.tcx.is_automatically_derived(data.impl_or_alias_def_id)
2009+
&& data.impl_or_alias_def_id.is_local()
2010+
}
2011+
_ => false,
2012+
}) {
2013+
diag.help(manually_impl);
2014+
suggest_derive = false;
2015+
}
2016+
} else {
2017+
diag.help(format!(
2018+
"{msg}: {}",
2019+
listify(&errors, |e| format!("`{}`", e.obligation.predicate))
2020+
.unwrap(),
2021+
));
2022+
}
19542023
}
19552024
}
19562025
for error in errors {
@@ -1968,7 +2037,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19682037
}
19692038
}
19702039
}
1971-
self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]);
2040+
if suggest_derive {
2041+
self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]);
2042+
}
19722043
}
19732044
}
19742045
}

0 commit comments

Comments
 (0)