Skip to content

Commit f4008fe

Browse files
committed
Auto merge of rust-lang#81905 - Dylan-DPC:rollup-mxpz1j7, r=Dylan-DPC
Rollup of 11 pull requests Successful merges: - rust-lang#72209 (Add checking for no_mangle to unsafe_code lint) - rust-lang#80732 (Allow Trait inheritance with cycles on associated types take 2) - rust-lang#81697 (Add "every" as a doc alias for "all".) - rust-lang#81826 (Prefer match over combinators to make some Box methods inlineable) - rust-lang#81834 (Resolve typedef in HashMap lldb pretty-printer only if possible) - rust-lang#81841 ([rustbuild] Output rustdoc-json-types docs ) - rust-lang#81849 (Expand the docs for ops::ControlFlow a bit) - rust-lang#81876 (parser: Fix panic in 'const impl' recovery) - rust-lang#81882 (:arrow_up: rust-analyzer) - rust-lang#81888 (Fix pretty printer macro_rules with semicolon.) - rust-lang#81896 (Remove outdated comment in windows' mutex.rs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 36931ce + d2e204d commit f4008fe

Some content is hidden

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

48 files changed

+919
-182
lines changed

compiler/rustc_ast_pretty/src/pprust/state.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,9 @@ impl<'a> State<'a> {
13111311
true,
13121312
item.span,
13131313
);
1314+
if macro_def.body.need_semicolon() {
1315+
self.word(";");
1316+
}
13141317
}
13151318
}
13161319
self.ann.post(self, AnnNode::Item(item))

compiler/rustc_infer/src/traits/util.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use smallvec::smallvec;
22

33
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
4-
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
55
use rustc_middle::ty::outlives::Component;
66
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
7+
use rustc_span::symbol::Ident;
78

89
pub fn anonymize_predicate<'tcx>(
910
tcx: TyCtxt<'tcx>,
@@ -282,6 +283,44 @@ pub fn transitive_bounds<'tcx>(
282283
elaborate_trait_refs(tcx, bounds).filter_to_traits()
283284
}
284285

286+
/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
287+
/// define the given associated type `assoc_name`. It uses the
288+
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
289+
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
290+
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
291+
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
292+
tcx: TyCtxt<'tcx>,
293+
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
294+
assoc_name: Ident,
295+
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
296+
let mut stack: Vec<_> = bounds.collect();
297+
let mut visited = FxIndexSet::default();
298+
299+
std::iter::from_fn(move || {
300+
while let Some(trait_ref) = stack.pop() {
301+
let anon_trait_ref = tcx.anonymize_late_bound_regions(trait_ref);
302+
if visited.insert(anon_trait_ref) {
303+
let super_predicates = tcx.super_predicates_that_define_assoc_type((
304+
trait_ref.def_id(),
305+
Some(assoc_name),
306+
));
307+
for (super_predicate, _) in super_predicates.predicates {
308+
let bound_predicate = super_predicate.kind();
309+
let subst_predicate = super_predicate
310+
.subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
311+
if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
312+
stack.push(binder.value);
313+
}
314+
}
315+
316+
return Some(trait_ref);
317+
}
318+
}
319+
320+
return None;
321+
})
322+
}
323+
285324
///////////////////////////////////////////////////////////////////////////
286325
// Other
287326
///////////////////////////////////////////////////////////////////////////

compiler/rustc_lint/src/builtin.rs

+46
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ impl UnsafeCode {
328328

329329
cx.struct_span_lint(UNSAFE_CODE, span, decorate);
330330
}
331+
332+
fn report_overriden_symbol_name(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) {
333+
self.report_unsafe(cx, span, |lint| {
334+
lint.build(msg)
335+
.note(
336+
"the linker's behavior with multiple libraries exporting duplicate symbol \
337+
names is undefined and Rust cannot provide guarantees when you manually \
338+
override them",
339+
)
340+
.emit();
341+
})
342+
}
331343
}
332344

333345
impl EarlyLintPass for UnsafeCode {
@@ -367,6 +379,40 @@ impl EarlyLintPass for UnsafeCode {
367379
lint.build("implementation of an `unsafe` trait").emit()
368380
}),
369381

382+
ast::ItemKind::Fn(..) => {
383+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
384+
self.report_overriden_symbol_name(
385+
cx,
386+
attr.span,
387+
"declaration of a `no_mangle` function",
388+
);
389+
}
390+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
391+
self.report_overriden_symbol_name(
392+
cx,
393+
attr.span,
394+
"declaration of a function with `export_name`",
395+
);
396+
}
397+
}
398+
399+
ast::ItemKind::Static(..) => {
400+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
401+
self.report_overriden_symbol_name(
402+
cx,
403+
attr.span,
404+
"declaration of a `no_mangle` static",
405+
);
406+
}
407+
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
408+
self.report_overriden_symbol_name(
409+
cx,
410+
attr.span,
411+
"declaration of a static with `export_name`",
412+
);
413+
}
414+
}
415+
370416
_ => {}
371417
}
372418
}

compiler/rustc_middle/src/query/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,23 @@ rustc_queries! {
442442
/// full predicates are available (note that supertraits have
443443
/// additional acyclicity requirements).
444444
query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
445-
desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
445+
desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
446+
}
447+
448+
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
449+
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
450+
/// subset of super-predicates that reference traits that define the given associated type.
451+
/// This is used to avoid cycles in resolving types like `T::Item`.
452+
query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
453+
desc { |tcx| "computing the super traits of `{}`{}",
454+
tcx.def_path_str(key.0),
455+
if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
456+
}
446457
}
447458

448459
/// To avoid cycles within the predicates of a single item we compute
449460
/// per-type-parameter predicates for resolving `T::AssocTy`.
450-
query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
461+
query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
451462
desc { |tcx| "computing the bounds for type parameter `{}`", {
452463
let id = tcx.hir().local_def_id_to_hir_id(key.1);
453464
tcx.hir().ty_param_name(id)

compiler/rustc_middle/src/ty/context.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5252
use rustc_session::lint::{Level, Lint};
5353
use rustc_session::Session;
5454
use rustc_span::source_map::MultiSpan;
55-
use rustc_span::symbol::{kw, sym, Symbol};
55+
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5656
use rustc_span::{Span, DUMMY_SP};
5757
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
5858
use rustc_target::spec::abi;
@@ -2053,6 +2053,42 @@ impl<'tcx> TyCtxt<'tcx> {
20532053
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
20542054
}
20552055

2056+
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
2057+
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
2058+
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
2059+
self.super_traits_of(trait_def_id).any(|trait_did| {
2060+
self.associated_items(trait_did)
2061+
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
2062+
.is_some()
2063+
})
2064+
}
2065+
2066+
/// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally)
2067+
/// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
2068+
/// to identify which traits may define a given associated type to help avoid cycle errors.
2069+
/// Returns a `DefId` iterator.
2070+
fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
2071+
let mut set = FxHashSet::default();
2072+
let mut stack = vec![trait_def_id];
2073+
2074+
set.insert(trait_def_id);
2075+
2076+
iter::from_fn(move || -> Option<DefId> {
2077+
let trait_did = stack.pop()?;
2078+
let generic_predicates = self.super_predicates_of(trait_did);
2079+
2080+
for (predicate, _) in generic_predicates.predicates {
2081+
if let ty::PredicateKind::Trait(data, _) = predicate.kind().skip_binder() {
2082+
if set.insert(data.def_id()) {
2083+
stack.push(data.def_id());
2084+
}
2085+
}
2086+
}
2087+
2088+
Some(trait_did)
2089+
})
2090+
}
2091+
20562092
/// Given a closure signature, returns an equivalent fn signature. Detuples
20572093
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
20582094
/// you would get a `fn(u32, i32)`.

compiler/rustc_middle/src/ty/query/keys.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef};
77
use crate::ty::{self, Ty, TyCtxt};
88
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
99
use rustc_query_system::query::DefaultCacheSelector;
10-
use rustc_span::symbol::Symbol;
10+
use rustc_span::symbol::{Ident, Symbol};
1111
use rustc_span::{Span, DUMMY_SP};
1212

1313
/// The `Key` trait controls what types can legally be used as the key
@@ -160,6 +160,28 @@ impl Key for (LocalDefId, DefId) {
160160
}
161161
}
162162

163+
impl Key for (DefId, Option<Ident>) {
164+
type CacheSelector = DefaultCacheSelector;
165+
166+
fn query_crate(&self) -> CrateNum {
167+
self.0.krate
168+
}
169+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
170+
tcx.def_span(self.0)
171+
}
172+
}
173+
174+
impl Key for (DefId, LocalDefId, Ident) {
175+
type CacheSelector = DefaultCacheSelector;
176+
177+
fn query_crate(&self) -> CrateNum {
178+
self.0.krate
179+
}
180+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
181+
self.1.default_span(tcx)
182+
}
183+
}
184+
163185
impl Key for (CrateNum, DefId) {
164186
type CacheSelector = DefaultCacheSelector;
165187

compiler/rustc_parse/src/parser/item.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1010,9 +1010,18 @@ impl<'a> Parser<'a> {
10101010
) -> PResult<'a, ItemInfo> {
10111011
let impl_span = self.token.span;
10121012
let mut err = self.expected_ident_found();
1013-
let mut impl_info = self.parse_item_impl(attrs, defaultness)?;
1013+
1014+
// Only try to recover if this is implementing a trait for a type
1015+
let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
1016+
Ok(impl_info) => impl_info,
1017+
Err(mut recovery_error) => {
1018+
// Recovery failed, raise the "expected identifier" error
1019+
recovery_error.cancel();
1020+
return Err(err);
1021+
}
1022+
};
1023+
10141024
match impl_info.1 {
1015-
// only try to recover if this is implementing a trait for a type
10161025
ItemKind::Impl(box ImplKind {
10171026
of_trait: Some(ref trai), ref mut constness, ..
10181027
}) => {
@@ -1030,6 +1039,7 @@ impl<'a> Parser<'a> {
10301039
ItemKind::Impl { .. } => return Err(err),
10311040
_ => unreachable!(),
10321041
}
1042+
10331043
Ok(impl_info)
10341044
}
10351045

compiler/rustc_trait_selection/src/traits/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ pub use self::util::{
6565
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
6666
};
6767
pub use self::util::{
68-
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
68+
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
69+
SupertraitDefIds, Supertraits,
6970
};
7071

7172
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;

0 commit comments

Comments
 (0)