mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 14:07:04 +00:00
Auto merge of #81905 - Dylan-DPC:rollup-mxpz1j7, r=Dylan-DPC
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 (⬆️ 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
This commit is contained in:
commit
f4008fe949
@ -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))
|
||||
|
@ -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>,
|
||||
@ -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
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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 {
|
||||
@ -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`",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
@ -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)`.
|
||||
|
@ -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
|
||||
@ -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;
|
||||
|
||||
|
@ -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, ..
|
||||
}) => {
|
||||
@ -1030,6 +1039,7 @@ impl<'a> Parser<'a> {
|
||||
ItemKind::Impl { .. } => return Err(err),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Ok(impl_info)
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -49,9 +49,10 @@ pub trait AstConv<'tcx> {
|
||||
|
||||
fn default_constness_for_trait_bounds(&self) -> Constness;
|
||||
|
||||
/// Returns predicates in scope of the form `X: Foo`, where `X` is
|
||||
/// a type parameter `X` with the given id `def_id`. This is a
|
||||
/// subset of the full set of predicates.
|
||||
/// Returns predicates in scope of the form `X: Foo<T>`, where `X`
|
||||
/// is a type parameter `X` with the given id `def_id` and T
|
||||
/// matches `assoc_name`. This is a subset of the full set of
|
||||
/// predicates.
|
||||
///
|
||||
/// This is used for one specific purpose: resolving "short-hand"
|
||||
/// associated type references like `T::Item`. In principle, we
|
||||
@ -60,7 +61,12 @@ pub trait AstConv<'tcx> {
|
||||
/// but this can lead to cycle errors. The problem is that we have
|
||||
/// to do this resolution *in order to create the predicates in
|
||||
/// the first place*. Hence, we have this "special pass".
|
||||
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
|
||||
fn get_type_parameter_bounds(
|
||||
&self,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
assoc_name: Ident,
|
||||
) -> ty::GenericPredicates<'tcx>;
|
||||
|
||||
/// Returns the lifetime to use when a lifetime is omitted (and not elided).
|
||||
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
|
||||
@ -792,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
|
||||
// Returns `true` if a bounds list includes `?Sized`.
|
||||
pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
|
||||
pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// Try to find an unbound in bounds.
|
||||
@ -850,7 +856,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
fn add_bounds(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::GenericBound<'_>],
|
||||
ast_bounds: &[&hir::GenericBound<'_>],
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
) {
|
||||
let constness = self.default_constness_for_trait_bounds();
|
||||
@ -865,7 +871,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
|
||||
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
|
||||
.instantiate_lang_item_trait_ref(
|
||||
lang_item, span, hir_id, args, param_ty, bounds,
|
||||
*lang_item, *span, *hir_id, args, param_ty, bounds,
|
||||
),
|
||||
hir::GenericBound::Outlives(ref l) => bounds
|
||||
.region_bounds
|
||||
@ -896,6 +902,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ast_bounds: &[hir::GenericBound<'_>],
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span,
|
||||
) -> Bounds<'tcx> {
|
||||
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
|
||||
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
|
||||
}
|
||||
|
||||
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
||||
/// named `assoc_name` into ty::Bounds. Ignore the rest.
|
||||
pub fn compute_bounds_that_match_assoc_type(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::GenericBound<'_>],
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span,
|
||||
assoc_name: Ident,
|
||||
) -> Bounds<'tcx> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
for ast_bound in ast_bounds {
|
||||
if let Some(trait_ref) = ast_bound.trait_ref() {
|
||||
if let Some(trait_did) = trait_ref.trait_def_id() {
|
||||
if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
|
||||
result.push(ast_bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
|
||||
}
|
||||
|
||||
fn compute_bounds_inner(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[&hir::GenericBound<'_>],
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span,
|
||||
) -> Bounds<'tcx> {
|
||||
let mut bounds = Bounds::default();
|
||||
|
||||
@ -1098,7 +1140,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// parameter to have a skipped binder.
|
||||
let param_ty =
|
||||
tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
|
||||
self.add_bounds(param_ty, ast_bounds, bounds);
|
||||
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
|
||||
self.add_bounds(param_ty, &ast_bounds, bounds);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -1413,8 +1456,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ty_param_def_id, assoc_name, span,
|
||||
);
|
||||
|
||||
let predicates =
|
||||
&self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
|
||||
let predicates = &self
|
||||
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
|
||||
.predicates;
|
||||
|
||||
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
|
||||
|
||||
@ -1422,12 +1466,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let param_name = tcx.hir().ty_param_name(param_hir_id);
|
||||
self.one_bound_for_assoc_type(
|
||||
|| {
|
||||
traits::transitive_bounds(
|
||||
traits::transitive_bounds_that_define_assoc_type(
|
||||
tcx,
|
||||
predicates.iter().filter_map(|(p, _)| {
|
||||
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
|
||||
}),
|
||||
assoc_name,
|
||||
)
|
||||
.into_iter()
|
||||
},
|
||||
|| param_name.to_string(),
|
||||
assoc_name,
|
||||
|
@ -20,6 +20,7 @@ use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
|
||||
|
||||
@ -183,7 +184,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
fn get_type_parameter_bounds(
|
||||
&self,
|
||||
_: Span,
|
||||
def_id: DefId,
|
||||
_: Ident,
|
||||
) -> ty::GenericPredicates<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let item_id = tcx.hir().ty_param_owner(hir_id);
|
||||
|
@ -1,3 +1,4 @@
|
||||
// ignore-tidy-filelength
|
||||
//! "Collection" is the process of determining the type and other external
|
||||
//! details of each item in Rust. Collection is specifically concerned
|
||||
//! with *inter-procedural* things -- for example, for a function
|
||||
@ -77,6 +78,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
projection_ty_from_predicates,
|
||||
explicit_predicates_of,
|
||||
super_predicates_of,
|
||||
super_predicates_that_define_assoc_type,
|
||||
trait_explicit_predicates_and_bounds,
|
||||
type_param_predicates,
|
||||
trait_def,
|
||||
@ -308,8 +310,17 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id.expect_local()))
|
||||
fn get_type_parameter_bounds(
|
||||
&self,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
assoc_name: Ident,
|
||||
) -> ty::GenericPredicates<'tcx> {
|
||||
self.tcx.at(span).type_param_predicates((
|
||||
self.item_def_id,
|
||||
def_id.expect_local(),
|
||||
assoc_name,
|
||||
))
|
||||
}
|
||||
|
||||
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
|
||||
@ -490,7 +501,7 @@ fn get_new_lifetime_name<'tcx>(
|
||||
/// `X: Foo` where `X` is the type parameter `def_id`.
|
||||
fn type_param_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
(item_def_id, def_id): (DefId, LocalDefId),
|
||||
(item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
use rustc_hir::*;
|
||||
|
||||
@ -515,7 +526,7 @@ fn type_param_predicates(
|
||||
let mut result = parent
|
||||
.map(|parent| {
|
||||
let icx = ItemCtxt::new(tcx, parent);
|
||||
icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id())
|
||||
icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut extend = None;
|
||||
@ -558,12 +569,18 @@ fn type_param_predicates(
|
||||
|
||||
let icx = ItemCtxt::new(tcx, item_def_id);
|
||||
let extra_predicates = extend.into_iter().chain(
|
||||
icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
|
||||
.into_iter()
|
||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
|
||||
_ => false,
|
||||
}),
|
||||
icx.type_parameter_bounds_in_generics(
|
||||
ast_generics,
|
||||
param_id,
|
||||
ty,
|
||||
OnlySelfBounds(true),
|
||||
Some(assoc_name),
|
||||
)
|
||||
.into_iter()
|
||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
|
||||
_ => false,
|
||||
}),
|
||||
);
|
||||
result.predicates =
|
||||
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
|
||||
@ -581,6 +598,7 @@ impl ItemCtxt<'tcx> {
|
||||
param_id: hir::HirId,
|
||||
ty: Ty<'tcx>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
assoc_name: Option<Ident>,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let constness = self.default_constness_for_trait_bounds();
|
||||
let from_ty_params = ast_generics
|
||||
@ -591,6 +609,10 @@ impl ItemCtxt<'tcx> {
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|bounds| bounds.iter())
|
||||
.filter(|b| match assoc_name {
|
||||
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
|
||||
None => true,
|
||||
})
|
||||
.flat_map(|b| predicates_from_bound(self, ty, b, constness));
|
||||
|
||||
let from_where_clauses = ast_generics
|
||||
@ -609,12 +631,34 @@ impl ItemCtxt<'tcx> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
|
||||
bp.bounds
|
||||
.iter()
|
||||
.filter(|b| match assoc_name {
|
||||
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
|
||||
None => true,
|
||||
})
|
||||
.filter_map(move |b| bt.map(|bt| (bt, b)))
|
||||
})
|
||||
.flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
|
||||
|
||||
from_ty_params.chain(from_where_clauses).collect()
|
||||
}
|
||||
|
||||
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
|
||||
debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name);
|
||||
|
||||
match b {
|
||||
hir::GenericBound::Trait(poly_trait_ref, _) => {
|
||||
let trait_ref = &poly_trait_ref.trait_ref;
|
||||
if let Some(trait_did) = trait_ref.trait_def_id() {
|
||||
self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether this is the AST for a reference to the type
|
||||
@ -983,54 +1027,91 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
|
||||
/// the transitive super-predicates are converted.
|
||||
fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
|
||||
debug!("super_predicates(trait_def_id={:?})", trait_def_id);
|
||||
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
|
||||
tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
|
||||
}
|
||||
|
||||
let item = match tcx.hir().get(trait_hir_id) {
|
||||
Node::Item(item) => item,
|
||||
_ => bug!("trait_node_id {} is not an item", trait_hir_id),
|
||||
};
|
||||
|
||||
let (generics, bounds) = match item.kind {
|
||||
hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
|
||||
hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
|
||||
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
|
||||
};
|
||||
|
||||
let icx = ItemCtxt::new(tcx, trait_def_id);
|
||||
|
||||
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
|
||||
let self_param_ty = tcx.types.self_param;
|
||||
let superbounds1 =
|
||||
AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
|
||||
|
||||
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
|
||||
|
||||
// Convert any explicit superbounds in the where-clause,
|
||||
// e.g., `trait Foo where Self: Bar`.
|
||||
// In the case of trait aliases, however, we include all bounds in the where-clause,
|
||||
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
|
||||
// as one of its "superpredicates".
|
||||
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
|
||||
let superbounds2 = icx.type_parameter_bounds_in_generics(
|
||||
generics,
|
||||
item.hir_id,
|
||||
self_param_ty,
|
||||
OnlySelfBounds(!is_trait_alias),
|
||||
/// Ensures that the super-predicates of the trait with a `DefId`
|
||||
/// of `trait_def_id` are converted and stored. This also ensures that
|
||||
/// the transitive super-predicates are converted.
|
||||
fn super_predicates_that_define_assoc_type(
|
||||
tcx: TyCtxt<'_>,
|
||||
(trait_def_id, assoc_name): (DefId, Option<Ident>),
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
debug!(
|
||||
"super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})",
|
||||
trait_def_id, assoc_name
|
||||
);
|
||||
if trait_def_id.is_local() {
|
||||
debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id);
|
||||
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
|
||||
|
||||
// Combine the two lists to form the complete set of superbounds:
|
||||
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
|
||||
let item = match tcx.hir().get(trait_hir_id) {
|
||||
Node::Item(item) => item,
|
||||
_ => bug!("trait_node_id {} is not an item", trait_hir_id),
|
||||
};
|
||||
|
||||
// Now require that immediate supertraits are converted,
|
||||
// which will, in turn, reach indirect supertraits.
|
||||
for &(pred, span) in superbounds {
|
||||
debug!("superbound: {:?}", pred);
|
||||
if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
|
||||
tcx.at(span).super_predicates_of(bound.def_id());
|
||||
let (generics, bounds) = match item.kind {
|
||||
hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
|
||||
hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
|
||||
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
|
||||
};
|
||||
|
||||
let icx = ItemCtxt::new(tcx, trait_def_id);
|
||||
|
||||
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
|
||||
let self_param_ty = tcx.types.self_param;
|
||||
let superbounds1 = if let Some(assoc_name) = assoc_name {
|
||||
AstConv::compute_bounds_that_match_assoc_type(
|
||||
&icx,
|
||||
self_param_ty,
|
||||
&bounds,
|
||||
SizedByDefault::No,
|
||||
item.span,
|
||||
assoc_name,
|
||||
)
|
||||
} else {
|
||||
AstConv::compute_bounds(&icx, self_param_ty, &bounds, SizedByDefault::No, item.span)
|
||||
};
|
||||
|
||||
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
|
||||
|
||||
// Convert any explicit superbounds in the where-clause,
|
||||
// e.g., `trait Foo where Self: Bar`.
|
||||
// In the case of trait aliases, however, we include all bounds in the where-clause,
|
||||
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
|
||||
// as one of its "superpredicates".
|
||||
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
|
||||
let superbounds2 = icx.type_parameter_bounds_in_generics(
|
||||
generics,
|
||||
item.hir_id,
|
||||
self_param_ty,
|
||||
OnlySelfBounds(!is_trait_alias),
|
||||
assoc_name,
|
||||
);
|
||||
|
||||
// Combine the two lists to form the complete set of superbounds:
|
||||
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
|
||||
|
||||
// Now require that immediate supertraits are converted,
|
||||
// which will, in turn, reach indirect supertraits.
|
||||
if assoc_name.is_none() {
|
||||
// Now require that immediate supertraits are converted,
|
||||
// which will, in turn, reach indirect supertraits.
|
||||
for &(pred, span) in superbounds {
|
||||
debug!("superbound: {:?}", pred);
|
||||
if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
|
||||
tcx.at(span).super_predicates_of(bound.def_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::GenericPredicates { parent: None, predicates: superbounds }
|
||||
ty::GenericPredicates { parent: None, predicates: superbounds }
|
||||
} else {
|
||||
// if `assoc_name` is None, then the query should've been redirected to an
|
||||
// external provider
|
||||
assert!(assoc_name.is_some());
|
||||
tcx.super_predicates_of(trait_def_id)
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
||||
|
@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, assoc_item_def_id),
|
||||
item_ty,
|
||||
bounds,
|
||||
&bounds,
|
||||
SizedByDefault::Yes,
|
||||
span,
|
||||
);
|
||||
@ -69,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, opaque_def_id),
|
||||
item_ty,
|
||||
bounds,
|
||||
&bounds,
|
||||
SizedByDefault::Yes,
|
||||
span,
|
||||
)
|
||||
|
@ -390,7 +390,12 @@ impl<T, A: Allocator> Box<T, A> {
|
||||
// #[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
|
||||
let layout = Layout::new::<mem::MaybeUninit<T>>();
|
||||
Box::try_new_uninit_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
|
||||
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
|
||||
// That would make code size bigger.
|
||||
match Box::try_new_uninit_in(alloc) {
|
||||
Ok(m) => m,
|
||||
Err(_) => handle_alloc_error(layout),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new box with uninitialized contents in the provided allocator,
|
||||
@ -447,7 +452,12 @@ impl<T, A: Allocator> Box<T, A> {
|
||||
// #[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
|
||||
let layout = Layout::new::<mem::MaybeUninit<T>>();
|
||||
Box::try_new_zeroed_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
|
||||
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
|
||||
// That would make code size bigger.
|
||||
match Box::try_new_zeroed_in(alloc) {
|
||||
Ok(m) => m,
|
||||
Err(_) => handle_alloc_error(layout),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new `Box` with uninitialized contents, with the memory
|
||||
|
@ -2205,6 +2205,7 @@ pub trait Iterator {
|
||||
/// // we can still use `iter`, as there are more elements.
|
||||
/// assert_eq!(iter.next(), Some(&3));
|
||||
/// ```
|
||||
#[doc(alias = "every")]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn all<F>(&mut self, f: F) -> bool
|
||||
|
@ -1,13 +1,63 @@
|
||||
use crate::ops::Try;
|
||||
|
||||
/// Used to make try_fold closures more like normal loops
|
||||
/// Used to tell an operation whether it should exit early or go on as usual.
|
||||
///
|
||||
/// This is used when exposing things (like graph traversals or visitors) where
|
||||
/// you want the user to be able to choose whether to exit early.
|
||||
/// Having the enum makes it clearer -- no more wondering "wait, what did `false`
|
||||
/// mean again?" -- and allows including a value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Early-exiting from [`Iterator::try_for_each`]:
|
||||
/// ```
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// let r = (2..100).try_for_each(|x| {
|
||||
/// if 403 % x == 0 {
|
||||
/// return ControlFlow::Break(x)
|
||||
/// }
|
||||
///
|
||||
/// ControlFlow::Continue(())
|
||||
/// });
|
||||
/// assert_eq!(r, ControlFlow::Break(13));
|
||||
/// ```
|
||||
///
|
||||
/// A basic tree traversal:
|
||||
/// ```no_run
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// pub struct TreeNode<T> {
|
||||
/// value: T,
|
||||
/// left: Option<Box<TreeNode<T>>>,
|
||||
/// right: Option<Box<TreeNode<T>>>,
|
||||
/// }
|
||||
///
|
||||
/// impl<T> TreeNode<T> {
|
||||
/// pub fn traverse_inorder<B>(&self, mut f: impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
|
||||
/// if let Some(left) = &self.left {
|
||||
/// left.traverse_inorder(&mut f)?;
|
||||
/// }
|
||||
/// f(&self.value)?;
|
||||
/// if let Some(right) = &self.right {
|
||||
/// right.traverse_inorder(&mut f)?;
|
||||
/// }
|
||||
/// ControlFlow::Continue(())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ControlFlow<B, C = ()> {
|
||||
/// Continue in the loop, using the given value for the next iteration
|
||||
/// Move on to the next phase of the operation as normal.
|
||||
Continue(C),
|
||||
/// Exit the loop, yielding the given value
|
||||
/// Exit the operation without running subsequent phases.
|
||||
Break(B),
|
||||
// Yes, the order of the variants doesn't match the type parameters.
|
||||
// They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
|
||||
// is a no-op conversion in the `Try` implementation.
|
||||
}
|
||||
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
@ -33,6 +83,16 @@ impl<B, C> Try for ControlFlow<B, C> {
|
||||
|
||||
impl<B, C> ControlFlow<B, C> {
|
||||
/// Returns `true` if this is a `Break` variant.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// assert!(ControlFlow::<i32, String>::Break(3).is_break());
|
||||
/// assert!(!ControlFlow::<String, i32>::Continue(3).is_break());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
pub fn is_break(&self) -> bool {
|
||||
@ -40,6 +100,16 @@ impl<B, C> ControlFlow<B, C> {
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a `Continue` variant.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// assert!(!ControlFlow::<i32, String>::Break(3).is_continue());
|
||||
/// assert!(ControlFlow::<String, i32>::Continue(3).is_continue());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
pub fn is_continue(&self) -> bool {
|
||||
@ -48,6 +118,16 @@ impl<B, C> ControlFlow<B, C> {
|
||||
|
||||
/// Converts the `ControlFlow` into an `Option` which is `Some` if the
|
||||
/// `ControlFlow` was `Break` and `None` otherwise.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3));
|
||||
/// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
pub fn break_value(self) -> Option<B> {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#![feature(const_maybe_uninit_assume_init)]
|
||||
#![feature(const_ptr_read)]
|
||||
#![feature(const_ptr_offset)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
|
@ -1,3 +1,5 @@
|
||||
mod control_flow;
|
||||
|
||||
use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
|
18
library/core/tests/ops/control_flow.rs
Normal file
18
library/core/tests/ops/control_flow.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use core::intrinsics::discriminant_value;
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
#[test]
|
||||
fn control_flow_discriminants_match_result() {
|
||||
// This isn't stable surface area, but helps keep `?` cheap between them,
|
||||
// even if LLVM can't always take advantage of it right now.
|
||||
// (Sadly Result and Option are inconsistent, so ControlFlow can't match both.)
|
||||
|
||||
assert_eq!(
|
||||
discriminant_value(&ControlFlow::<i32, i32>::Break(3)),
|
||||
discriminant_value(&Result::<i32, i32>::Err(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
discriminant_value(&ControlFlow::<i32, i32>::Continue(3)),
|
||||
discriminant_value(&Result::<i32, i32>::Ok(3)),
|
||||
);
|
||||
}
|
@ -23,8 +23,6 @@ pub struct Mutex {
|
||||
}
|
||||
|
||||
// Windows SRW Locks are movable (while not borrowed).
|
||||
// ReentrantMutexes (in Inner) are not, but those are stored indirectly through
|
||||
// a Box, so do not move when the Mutex it self is moved.
|
||||
pub type MovableMutex = Mutex;
|
||||
|
||||
unsafe impl Send for Mutex {}
|
||||
|
@ -626,6 +626,7 @@ impl Step for Rustdoc {
|
||||
// Only include compiler crates, no dependencies of those, such as `libc`.
|
||||
cargo.arg("--no-deps");
|
||||
cargo.arg("-p").arg("rustdoc");
|
||||
cargo.arg("-p").arg("rustdoc-json-types");
|
||||
|
||||
cargo.rustdocflag("--document-private-items");
|
||||
cargo.rustdocflag("--enable-index-page");
|
||||
|
@ -531,7 +531,9 @@ class StdHashMapSyntheticProvider:
|
||||
ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
|
||||
|
||||
self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned()
|
||||
self.pair_type = table.type.template_args[0].GetTypedefedType()
|
||||
self.pair_type = table.type.template_args[0]
|
||||
if self.pair_type.IsTypedefType():
|
||||
self.pair_type = self.pair_type.GetTypedefedType()
|
||||
self.pair_type_size = self.pair_type.GetByteSize()
|
||||
|
||||
self.new_layout = not table.GetChildMemberWithName("data").IsValid()
|
||||
|
@ -3,11 +3,11 @@
|
||||
// revisions: rpass1 cfail2
|
||||
|
||||
#[cfg(rpass1)]
|
||||
pub trait T2 { }
|
||||
pub trait T2 {}
|
||||
#[cfg(cfail2)]
|
||||
pub trait T2: T1 { }
|
||||
//[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
|
||||
pub trait T2: T1 {}
|
||||
//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2`
|
||||
|
||||
pub trait T1: T2 { }
|
||||
pub trait T1: T2 {}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
19
src/test/pretty/macro_rules.rs
Normal file
19
src/test/pretty/macro_rules.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// pp-exact
|
||||
|
||||
macro_rules! brace { () => { } ; }
|
||||
|
||||
macro_rules! bracket[() => { } ;];
|
||||
|
||||
macro_rules! paren(() => { } ;);
|
||||
|
||||
macro_rules! matcher_brackets {
|
||||
(paren) => { } ; (bracket) => { } ; (brace) => { } ;
|
||||
}
|
||||
|
||||
macro_rules! all_fragments {
|
||||
($ b : block, $ e : expr, $ i : ident, $ it : item, $ l : lifetime, $ lit
|
||||
: literal, $ m : meta, $ p : pat, $ pth : path, $ s : stmt, $ tt : tt, $
|
||||
ty : ty, $ vis : vis) => { } ;
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,12 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
trait Foo {
|
||||
type Item;
|
||||
}
|
||||
trait Bar<T> {
|
||||
type Item;
|
||||
}
|
||||
trait Baz: Foo + Bar<Self::Item> {}
|
||||
//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391]
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item`
|
||||
--> $DIR/ambiguous-associated-type2.rs:9:1
|
||||
|
|
||||
LL | trait Baz: Foo + Bar<Self::Item> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle
|
||||
note: cycle used when computing the super traits of `Baz`
|
||||
--> $DIR/ambiguous-associated-type2.rs:9:1
|
||||
|
|
||||
LL | trait Baz: Foo + Bar<Self::Item> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
@ -0,0 +1,21 @@
|
||||
// check-pass
|
||||
|
||||
trait Foo {
|
||||
type Item;
|
||||
}
|
||||
|
||||
trait Bar
|
||||
where
|
||||
Self: Foo,
|
||||
{
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn foo<M>(_m: M)
|
||||
where
|
||||
M: Bar,
|
||||
M::Item: Send,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,10 @@
|
||||
// check-pass
|
||||
|
||||
trait Foo<T> {}
|
||||
trait Bar {
|
||||
type A;
|
||||
type B;
|
||||
}
|
||||
trait Baz: Bar<B = u32> + Foo<Self::A> {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,10 @@
|
||||
#[allow(dead_code)]
|
||||
fn foo<M>(_m: M)
|
||||
where
|
||||
M::Item: Temp,
|
||||
//~^ ERROR cannot find trait `Temp` in this scope [E0405]
|
||||
//~| ERROR associated type `Item` not found for `M` [E0220]
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0405]: cannot find trait `Temp` in this scope
|
||||
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14
|
||||
|
|
||||
LL | M::Item: Temp,
|
||||
| ^^^^ not found in this scope
|
||||
|
||||
error[E0220]: associated type `Item` not found for `M`
|
||||
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
|
||||
|
|
||||
LL | M::Item: Temp,
|
||||
| ^^^^ associated type `Item` not found
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0220, E0405.
|
||||
For more information about an error, try `rustc --explain E0220`.
|
@ -0,0 +1,12 @@
|
||||
// check-pass
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
trait Qux: Foo + AsRef<Self::Bar> {}
|
||||
trait Foo2 {}
|
||||
|
||||
trait Qux2: Foo2 + AsRef<Self::Bar> {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,19 @@
|
||||
// check-pass
|
||||
|
||||
// The goal of this test is to ensure that T: Bar<T::Item>
|
||||
// in the where clause does not cycle
|
||||
|
||||
trait Foo {
|
||||
type Item;
|
||||
}
|
||||
|
||||
trait Bar<T> {}
|
||||
|
||||
fn baz<T>()
|
||||
where
|
||||
T: Foo,
|
||||
T: Bar<T::Item>,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,27 @@
|
||||
// check-pass
|
||||
|
||||
// Test that we do not get a cycle due to
|
||||
// resolving `Self::Bar` in the where clauses
|
||||
// on a trait definition (in particular, in
|
||||
// a where clause that is defining a superpredicate).
|
||||
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
trait Qux
|
||||
where
|
||||
Self: Foo,
|
||||
Self: AsRef<Self::Bar>,
|
||||
{
|
||||
}
|
||||
trait Foo2 {}
|
||||
|
||||
trait Qux2
|
||||
where
|
||||
Self: Foo2,
|
||||
Self: AsRef<Self::Bar>,
|
||||
{
|
||||
type Bar;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,33 @@
|
||||
// check-pass
|
||||
|
||||
pub struct LookupInternedStorage;
|
||||
|
||||
impl<Q> QueryStorageOps<Q> for LookupInternedStorage
|
||||
where
|
||||
Q: Query,
|
||||
for<'d> Q: QueryDb<'d>,
|
||||
{
|
||||
fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb) {
|
||||
<<Q as QueryDb<'_>>::DynDb as HasQueryGroup<Q::Group>>::group_storage(db);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasQueryGroup<G> {
|
||||
fn group_storage(&self);
|
||||
}
|
||||
|
||||
pub trait QueryStorageOps<Q>
|
||||
where
|
||||
Q: Query,
|
||||
{
|
||||
fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb);
|
||||
}
|
||||
|
||||
pub trait QueryDb<'d> {
|
||||
type DynDb: HasQueryGroup<Self::Group> + 'd;
|
||||
type Group;
|
||||
}
|
||||
|
||||
pub trait Query: for<'d> QueryDb<'d> {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,43 @@
|
||||
// check-pass
|
||||
// compile-flags:-Cincremental=tmp/traits-assoc-type-macros
|
||||
|
||||
// This test case makes sure that we can compile with incremental compilation
|
||||
// enabled when there are macros, traits, inheritance and associated types involved.
|
||||
|
||||
trait Deserializer {
|
||||
type Error;
|
||||
}
|
||||
|
||||
trait Deserialize {
|
||||
fn deserialize<D>(_: D) -> D::Error
|
||||
where
|
||||
D: Deserializer;
|
||||
}
|
||||
|
||||
macro_rules! impl_deserialize {
|
||||
($name:ident) => {
|
||||
impl Deserialize for $name {
|
||||
fn deserialize<D>(_: D) -> D::Error
|
||||
where
|
||||
D: Deserializer,
|
||||
{
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! formats {
|
||||
{
|
||||
$($name:ident,)*
|
||||
} => {
|
||||
$(
|
||||
pub struct $name;
|
||||
|
||||
impl_deserialize!($name);
|
||||
)*
|
||||
}
|
||||
}
|
||||
formats! { Foo, Bar, }
|
||||
|
||||
fn main() {}
|
@ -1,24 +0,0 @@
|
||||
// Example cycle where a bound on `T` uses a shorthand for `T`. This
|
||||
// creates a cycle because we have to know the bounds on `T` to figure
|
||||
// out what trait defines `Item`, but we can't know the bounds on `T`
|
||||
// without knowing how to handle `T::Item`.
|
||||
//
|
||||
// Note that in the future cases like this could perhaps become legal,
|
||||
// if we got more fine-grained about our cycle detection or changed
|
||||
// how we handle `T::Item` resolution.
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
// Preamble.
|
||||
trait Trait { type Item; }
|
||||
|
||||
struct A<T>
|
||||
where T : Trait,
|
||||
T : Add<T::Item>
|
||||
//~^ ERROR cycle detected
|
||||
{
|
||||
data: T
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
error[E0391]: cycle detected when computing the bounds for type parameter `T`
|
||||
--> $DIR/cycle-projection-based-on-where-clause.rs:17:19
|
||||
|
|
||||
LL | T : Add<T::Item>
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: ...which again requires computing the bounds for type parameter `T`, completing the cycle
|
||||
note: cycle used when computing explicit predicates of `A`
|
||||
--> $DIR/cycle-projection-based-on-where-clause.rs:17:19
|
||||
|
|
||||
LL | T : Add<T::Item>
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
@ -1,10 +1,15 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `Chromosome`
|
||||
error[E0391]: cycle detected when computing the super predicates of `Chromosome`
|
||||
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
|
||||
|
|
||||
LL | trait Chromosome: Chromosome {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing the super traits of `Chromosome`...
|
||||
--> $DIR/cycle-trait-supertrait-direct.rs:3:19
|
||||
|
|
||||
LL | trait Chromosome: Chromosome {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle
|
||||
= note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
|
||||
|
|
||||
|
@ -1,16 +1,26 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `B`
|
||||
error[E0391]: cycle detected when computing the super predicates of `B`
|
||||
--> $DIR/cycle-trait-supertrait-indirect.rs:7:1
|
||||
|
|
||||
LL | trait B: C {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing the super traits of `B`...
|
||||
--> $DIR/cycle-trait-supertrait-indirect.rs:7:10
|
||||
|
|
||||
LL | trait B: C {
|
||||
| ^
|
||||
note: ...which requires computing the super predicates of `C`...
|
||||
--> $DIR/cycle-trait-supertrait-indirect.rs:11:1
|
||||
|
|
||||
note: ...which requires computing the supertraits of `C`...
|
||||
LL | trait C: B { }
|
||||
| ^^^^^^^^^^
|
||||
note: ...which requires computing the super traits of `C`...
|
||||
--> $DIR/cycle-trait-supertrait-indirect.rs:11:10
|
||||
|
|
||||
LL | trait C: B { }
|
||||
| ^
|
||||
= note: ...which again requires computing the supertraits of `B`, completing the cycle
|
||||
note: cycle used when computing the supertraits of `A`
|
||||
= note: ...which again requires computing the super predicates of `B`, completing the cycle
|
||||
note: cycle used when computing the super traits of `A`
|
||||
--> $DIR/cycle-trait-supertrait-indirect.rs:4:10
|
||||
|
|
||||
LL | trait A: B {
|
||||
|
@ -1,15 +1,25 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `T1`
|
||||
error[E0391]: cycle detected when computing the super predicates of `T1`
|
||||
--> $DIR/issue-12511.rs:1:1
|
||||
|
|
||||
LL | trait T1 : T2 {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing the super traits of `T1`...
|
||||
--> $DIR/issue-12511.rs:1:12
|
||||
|
|
||||
LL | trait T1 : T2 {
|
||||
| ^^
|
||||
note: ...which requires computing the super predicates of `T2`...
|
||||
--> $DIR/issue-12511.rs:5:1
|
||||
|
|
||||
note: ...which requires computing the supertraits of `T2`...
|
||||
LL | trait T2 : T1 {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires computing the super traits of `T2`...
|
||||
--> $DIR/issue-12511.rs:5:12
|
||||
|
|
||||
LL | trait T2 : T1 {
|
||||
| ^^
|
||||
= note: ...which again requires computing the supertraits of `T1`, completing the cycle
|
||||
= note: ...which again requires computing the super predicates of `T1`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-12511.rs:1:1
|
||||
|
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `T`
|
||||
error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item`
|
||||
--> $DIR/issue-20772.rs:1:1
|
||||
|
|
||||
LL | / trait T : Iterator<Item=Self::Item>
|
||||
@ -6,8 +6,8 @@ LL | |
|
||||
LL | | {}
|
||||
| |__^
|
||||
|
|
||||
= note: ...which again requires computing the supertraits of `T`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
= note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle
|
||||
note: cycle used when computing the super traits of `T`
|
||||
--> $DIR/issue-20772.rs:1:1
|
||||
|
|
||||
LL | / trait T : Iterator<Item=Self::Item>
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `Processor`
|
||||
error[E0391]: cycle detected when computing the super traits of `Processor` with associated type name `Input`
|
||||
--> $DIR/issue-20825.rs:5:1
|
||||
|
|
||||
LL | pub trait Processor: Subscriber<Input = Self::Input> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires computing the supertraits of `Processor`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
= note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle
|
||||
note: cycle used when computing the super traits of `Processor`
|
||||
--> $DIR/issue-20825.rs:5:1
|
||||
|
|
||||
LL | pub trait Processor: Subscriber<Input = Self::Input> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
trait Expr : PartialEq<Self::Item> {
|
||||
//~^ ERROR: cycle detected
|
||||
// check-pass
|
||||
|
||||
trait Expr: PartialEq<Self::Item> {
|
||||
type Item;
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
error[E0391]: cycle detected when computing the supertraits of `Expr`
|
||||
--> $DIR/issue-22673.rs:1:1
|
||||
|
|
||||
LL | trait Expr : PartialEq<Self::Item> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires computing the supertraits of `Expr`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-22673.rs:1:1
|
||||
|
|
||||
LL | trait Expr : PartialEq<Self::Item> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
@ -12,14 +12,28 @@ mod allowed_unsafe {
|
||||
unsafe fn also_allowed() {}
|
||||
unsafe trait AllowedUnsafe { }
|
||||
unsafe impl AllowedUnsafe for super::Bar {}
|
||||
#[no_mangle] fn allowed2() {}
|
||||
#[export_name = "foo"] fn allowed3() {}
|
||||
}
|
||||
|
||||
macro_rules! unsafe_in_macro {
|
||||
() => {
|
||||
() => {{
|
||||
#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
|
||||
#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
|
||||
#[export_name = "bar"] fn bar() {}
|
||||
//~^ ERROR: declaration of a function with `export_name`
|
||||
#[export_name = "BAR"] static BAR: u32 = 5;
|
||||
//~^ ERROR: declaration of a static with `export_name`
|
||||
unsafe {} //~ ERROR: usage of an `unsafe` block
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
|
||||
#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
|
||||
|
||||
#[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name`
|
||||
#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name`
|
||||
|
||||
unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
|
||||
unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
|
||||
unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
|
||||
|
@ -1,89 +1,168 @@
|
||||
error: declaration of an `unsafe` function
|
||||
--> $DIR/lint-unsafe-code.rs:23:1
|
||||
error: declaration of a `no_mangle` function
|
||||
--> $DIR/lint-unsafe-code.rs:31:1
|
||||
|
|
||||
LL | unsafe fn baz() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
LL | #[no_mangle] fn foo() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-unsafe-code.rs:3:9
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
error: declaration of a `no_mangle` static
|
||||
--> $DIR/lint-unsafe-code.rs:32:1
|
||||
|
|
||||
LL | #[no_mangle] static FOO: u32 = 5;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
error: declaration of a function with `export_name`
|
||||
--> $DIR/lint-unsafe-code.rs:34:1
|
||||
|
|
||||
LL | #[export_name = "bar"] fn bar() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
error: declaration of a static with `export_name`
|
||||
--> $DIR/lint-unsafe-code.rs:35:1
|
||||
|
|
||||
LL | #[export_name = "BAR"] static BAR: u32 = 5;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
error: declaration of an `unsafe` function
|
||||
--> $DIR/lint-unsafe-code.rs:37:1
|
||||
|
|
||||
LL | unsafe fn baz() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: declaration of an `unsafe` trait
|
||||
--> $DIR/lint-unsafe-code.rs:24:1
|
||||
--> $DIR/lint-unsafe-code.rs:38:1
|
||||
|
|
||||
LL | unsafe trait Foo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` trait
|
||||
--> $DIR/lint-unsafe-code.rs:25:1
|
||||
--> $DIR/lint-unsafe-code.rs:39:1
|
||||
|
|
||||
LL | unsafe impl Foo for Bar {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: declaration of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:28:5
|
||||
--> $DIR/lint-unsafe-code.rs:42:5
|
||||
|
|
||||
LL | unsafe fn baz(&self);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:29:5
|
||||
--> $DIR/lint-unsafe-code.rs:43:5
|
||||
|
|
||||
LL | unsafe fn provided(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:30:5
|
||||
--> $DIR/lint-unsafe-code.rs:44:5
|
||||
|
|
||||
LL | unsafe fn provided_override(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:34:5
|
||||
--> $DIR/lint-unsafe-code.rs:48:5
|
||||
|
|
||||
LL | unsafe fn baz(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:35:5
|
||||
--> $DIR/lint-unsafe-code.rs:49:5
|
||||
|
|
||||
LL | unsafe fn provided_override(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:54:5
|
||||
--> $DIR/lint-unsafe-code.rs:68:5
|
||||
|
|
||||
LL | unsafe fn provided_override(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:65:5
|
||||
--> $DIR/lint-unsafe-code.rs:79:5
|
||||
|
|
||||
LL | unsafe fn provided(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:71:5
|
||||
--> $DIR/lint-unsafe-code.rs:85:5
|
||||
|
|
||||
LL | unsafe fn provided(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation of an `unsafe` method
|
||||
--> $DIR/lint-unsafe-code.rs:75:5
|
||||
--> $DIR/lint-unsafe-code.rs:89:5
|
||||
|
|
||||
LL | unsafe fn baz(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-unsafe-code.rs:86:5
|
||||
--> $DIR/lint-unsafe-code.rs:100:5
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: declaration of a `no_mangle` function
|
||||
--> $DIR/lint-unsafe-code.rs:21:9
|
||||
|
|
||||
LL | #[no_mangle] fn foo() {}
|
||||
| ^^^^^^^^^^^^
|
||||
...
|
||||
LL | unsafe_in_macro!()
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: declaration of a `no_mangle` static
|
||||
--> $DIR/lint-unsafe-code.rs:22:9
|
||||
|
|
||||
LL | #[no_mangle] static FOO: u32 = 5;
|
||||
| ^^^^^^^^^^^^
|
||||
...
|
||||
LL | unsafe_in_macro!()
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: declaration of a function with `export_name`
|
||||
--> $DIR/lint-unsafe-code.rs:23:9
|
||||
|
|
||||
LL | #[export_name = "bar"] fn bar() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | unsafe_in_macro!()
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: declaration of a static with `export_name`
|
||||
--> $DIR/lint-unsafe-code.rs:25:9
|
||||
|
|
||||
LL | #[export_name = "BAR"] static BAR: u32 = 5;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | unsafe_in_macro!()
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-unsafe-code.rs:19:9
|
||||
--> $DIR/lint-unsafe-code.rs:27:9
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
@ -93,5 +172,5 @@ LL | unsafe_in_macro!()
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
5
src/test/ui/parser/issue-81806.rs
Normal file
5
src/test/ui/parser/issue-81806.rs
Normal file
@ -0,0 +1,5 @@
|
||||
trait T { const
|
||||
impl //~ ERROR: expected identifier, found keyword `impl`
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/ui/parser/issue-81806.stderr
Normal file
17
src/test/ui/parser/issue-81806.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: expected identifier, found keyword `impl`
|
||||
--> $DIR/issue-81806.rs:2:1
|
||||
|
|
||||
LL | trait T { const
|
||||
| - while parsing this item list starting here
|
||||
LL | impl
|
||||
| ^^^^ expected identifier, found keyword
|
||||
LL | }
|
||||
| - the item list ends here
|
||||
|
|
||||
help: you can escape reserved keywords to use them as identifiers
|
||||
|
|
||||
LL | r#impl
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 1a59f75cdaa730c16a694a4294eccf6dfe6fe0ad
|
||||
Subproject commit 336909b63a14b801520c6627d90d750babcfe280
|
Loading…
Reference in New Issue
Block a user