Skip to content

Commit

Permalink
Auto merge of #81905 - Dylan-DPC:rollup-mxpz1j7, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 11 pull requests

Successful merges:

 - #72209 (Add checking for no_mangle to unsafe_code lint)
 - #80732 (Allow Trait inheritance with cycles on associated types take 2)
 - #81697 (Add "every" as a doc alias for "all".)
 - #81826 (Prefer match over combinators to make some Box methods inlineable)
 - #81834 (Resolve typedef in HashMap lldb pretty-printer only if possible)
 - #81841 ([rustbuild] Output rustdoc-json-types docs )
 - #81849 (Expand the docs for ops::ControlFlow a bit)
 - #81876 (parser: Fix panic in 'const impl' recovery)
 - #81882 (:arrow_up: rust-analyzer)
 - #81888 (Fix pretty printer macro_rules with semicolon.)
 - #81896 (Remove outdated comment in windows' mutex.rs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Feb 9, 2021
2 parents 36931ce + d2e204d commit f4008fe
Show file tree
Hide file tree
Showing 48 changed files with 919 additions and 182 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Expand Up @@ -1311,6 +1311,9 @@ impl<'a> State<'a> {
true,
item.span,
);
if macro_def.body.need_semicolon() {
self.word(";");
}
}
}
self.ann.post(self, AnnNode::Item(item))
Expand Down
41 changes: 40 additions & 1 deletion compiler/rustc_infer/src/traits/util.rs
@@ -1,9 +1,10 @@
use smallvec::smallvec;

use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident;

pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -282,6 +283,44 @@ pub fn transitive_bounds<'tcx>(
elaborate_trait_refs(tcx, bounds).filter_to_traits()
}

/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
/// define the given associated type `assoc_name`. It uses the
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
tcx: TyCtxt<'tcx>,
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
assoc_name: Ident,
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
let mut stack: Vec<_> = bounds.collect();
let mut visited = FxIndexSet::default();

std::iter::from_fn(move || {
while let Some(trait_ref) = stack.pop() {
let anon_trait_ref = tcx.anonymize_late_bound_regions(trait_ref);
if visited.insert(anon_trait_ref) {
let super_predicates = tcx.super_predicates_that_define_assoc_type((
trait_ref.def_id(),
Some(assoc_name),
));
for (super_predicate, _) in super_predicates.predicates {
let bound_predicate = super_predicate.kind();
let subst_predicate = super_predicate
.subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
stack.push(binder.value);
}
}

return Some(trait_ref);
}
}

return None;
})
}

///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////
Expand Down
46 changes: 46 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Expand Up @@ -328,6 +328,18 @@ impl UnsafeCode {

cx.struct_span_lint(UNSAFE_CODE, span, decorate);
}

fn report_overriden_symbol_name(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) {
self.report_unsafe(cx, span, |lint| {
lint.build(msg)
.note(
"the linker's behavior with multiple libraries exporting duplicate symbol \
names is undefined and Rust cannot provide guarantees when you manually \
override them",
)
.emit();
})
}
}

impl EarlyLintPass for UnsafeCode {
Expand Down Expand Up @@ -367,6 +379,40 @@ impl EarlyLintPass for UnsafeCode {
lint.build("implementation of an `unsafe` trait").emit()
}),

ast::ItemKind::Fn(..) => {
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
self.report_overriden_symbol_name(
cx,
attr.span,
"declaration of a `no_mangle` function",
);
}
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
self.report_overriden_symbol_name(
cx,
attr.span,
"declaration of a function with `export_name`",
);
}
}

ast::ItemKind::Static(..) => {
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
self.report_overriden_symbol_name(
cx,
attr.span,
"declaration of a `no_mangle` static",
);
}
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
self.report_overriden_symbol_name(
cx,
attr.span,
"declaration of a static with `export_name`",
);
}
}

_ => {}
}
}
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Expand Up @@ -442,12 +442,23 @@ rustc_queries! {
/// full predicates are available (note that supertraits have
/// additional acyclicity requirements).
query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
}

/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
/// subset of super-predicates that reference traits that define the given associated type.
/// This is used to avoid cycles in resolving types like `T::Item`.
query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the super traits of `{}`{}",
tcx.def_path_str(key.0),
if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
}
}

/// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`.
query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the bounds for type parameter `{}`", {
let id = tcx.hir().local_def_id_to_hir_id(key.1);
tcx.hir().ty_param_name(id)
Expand Down
38 changes: 37 additions & 1 deletion compiler/rustc_middle/src/ty/context.rs
Expand Up @@ -52,7 +52,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint};
use rustc_session::Session;
use rustc_span::source_map::MultiSpan;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
Expand Down Expand Up @@ -2053,6 +2053,42 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
}

/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
self.super_traits_of(trait_def_id).any(|trait_did| {
self.associated_items(trait_did)
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
.is_some()
})
}

/// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally)
/// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
/// to identify which traits may define a given associated type to help avoid cycle errors.
/// Returns a `DefId` iterator.
fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
let mut set = FxHashSet::default();
let mut stack = vec![trait_def_id];

set.insert(trait_def_id);

iter::from_fn(move || -> Option<DefId> {
let trait_did = stack.pop()?;
let generic_predicates = self.super_predicates_of(trait_did);

for (predicate, _) in generic_predicates.predicates {
if let ty::PredicateKind::Trait(data, _) = predicate.kind().skip_binder() {
if set.insert(data.def_id()) {
stack.push(data.def_id());
}
}
}

Some(trait_did)
})
}

/// Given a closure signature, returns an equivalent fn signature. Detuples
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
/// you would get a `fn(u32, i32)`.
Expand Down
24 changes: 23 additions & 1 deletion compiler/rustc_middle/src/ty/query/keys.rs
Expand Up @@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_query_system::query::DefaultCacheSelector;
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};

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

impl Key for (DefId, Option<Ident>) {
type CacheSelector = DefaultCacheSelector;

fn query_crate(&self) -> CrateNum {
self.0.krate
}
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.0)
}
}

impl Key for (DefId, LocalDefId, Ident) {
type CacheSelector = DefaultCacheSelector;

fn query_crate(&self) -> CrateNum {
self.0.krate
}
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
}

impl Key for (CrateNum, DefId) {
type CacheSelector = DefaultCacheSelector;

Expand Down
14 changes: 12 additions & 2 deletions compiler/rustc_parse/src/parser/item.rs
Expand Up @@ -1010,9 +1010,18 @@ impl<'a> Parser<'a> {
) -> PResult<'a, ItemInfo> {
let impl_span = self.token.span;
let mut err = self.expected_ident_found();
let mut impl_info = self.parse_item_impl(attrs, defaultness)?;

// Only try to recover if this is implementing a trait for a type
let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
Ok(impl_info) => impl_info,
Err(mut recovery_error) => {
// Recovery failed, raise the "expected identifier" error
recovery_error.cancel();
return Err(err);
}
};

match impl_info.1 {
// only try to recover if this is implementing a trait for a type
ItemKind::Impl(box ImplKind {
of_trait: Some(ref trai), ref mut constness, ..
}) => {
Expand All @@ -1030,6 +1039,7 @@ impl<'a> Parser<'a> {
ItemKind::Impl { .. } => return Err(err),
_ => unreachable!(),
}

Ok(impl_info)
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Expand Up @@ -65,7 +65,8 @@ pub use self::util::{
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
};
pub use self::util::{
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
SupertraitDefIds, Supertraits,
};

pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
Expand Down

0 comments on commit f4008fe

Please sign in to comment.