Merge branch 'rust-lang:master' into issue-98861-fix
This commit is contained in:
commit
0436067210
162 changed files with 3121 additions and 973 deletions
|
@ -4626,6 +4626,7 @@ dependencies = [
|
||||||
"rustc_attr",
|
"rustc_attr",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
|
"rustc_feature",
|
||||||
"rustc_graphviz",
|
"rustc_graphviz",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_hir_pretty",
|
"rustc_hir_pretty",
|
||||||
|
|
|
@ -417,6 +417,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
|| attr.has_name(sym::stable)
|
|| attr.has_name(sym::stable)
|
||||||
|| attr.has_name(sym::rustc_const_unstable)
|
|| attr.has_name(sym::rustc_const_unstable)
|
||||||
|| attr.has_name(sym::rustc_const_stable)
|
|| attr.has_name(sym::rustc_const_stable)
|
||||||
|
|| attr.has_name(sym::rustc_default_body_unstable)
|
||||||
{
|
{
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
self.sess,
|
self.sess,
|
||||||
|
|
|
@ -131,6 +131,14 @@ impl ConstStability {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the `#[rustc_default_body_unstable]` attribute.
|
||||||
|
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[derive(HashStable_Generic)]
|
||||||
|
pub struct DefaultBodyStability {
|
||||||
|
pub level: StabilityLevel,
|
||||||
|
pub feature: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
/// The available stability levels.
|
/// The available stability levels.
|
||||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||||
#[derive(HashStable_Generic)]
|
#[derive(HashStable_Generic)]
|
||||||
|
@ -214,7 +222,8 @@ pub fn find_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>) {
|
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||||
|
{
|
||||||
find_stability_generic(sess, attrs.iter(), item_sp)
|
find_stability_generic(sess, attrs.iter(), item_sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +231,7 @@ fn find_stability_generic<'a, I>(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs_iter: I,
|
attrs_iter: I,
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>)
|
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a Attribute>,
|
I: Iterator<Item = &'a Attribute>,
|
||||||
{
|
{
|
||||||
|
@ -230,6 +239,7 @@ where
|
||||||
|
|
||||||
let mut stab: Option<(Stability, Span)> = None;
|
let mut stab: Option<(Stability, Span)> = None;
|
||||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||||
|
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||||
let mut promotable = false;
|
let mut promotable = false;
|
||||||
let mut allowed_through_unstable_modules = false;
|
let mut allowed_through_unstable_modules = false;
|
||||||
|
|
||||||
|
@ -243,6 +253,7 @@ where
|
||||||
sym::stable,
|
sym::stable,
|
||||||
sym::rustc_promotable,
|
sym::rustc_promotable,
|
||||||
sym::rustc_allowed_through_unstable_modules,
|
sym::rustc_allowed_through_unstable_modules,
|
||||||
|
sym::rustc_default_body_unstable,
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.any(|&s| attr.has_name(s))
|
.any(|&s| attr.has_name(s))
|
||||||
|
@ -280,7 +291,7 @@ where
|
||||||
|
|
||||||
let meta_name = meta.name_or_empty();
|
let meta_name = meta.name_or_empty();
|
||||||
match meta_name {
|
match meta_name {
|
||||||
sym::rustc_const_unstable | sym::unstable => {
|
sym::rustc_const_unstable | sym::rustc_default_body_unstable | sym::unstable => {
|
||||||
if meta_name == sym::unstable && stab.is_some() {
|
if meta_name == sym::unstable && stab.is_some() {
|
||||||
handle_errors(
|
handle_errors(
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
|
@ -295,6 +306,13 @@ where
|
||||||
AttrError::MultipleStabilityLevels,
|
AttrError::MultipleStabilityLevels,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
} else if meta_name == sym::rustc_default_body_unstable && body_stab.is_some() {
|
||||||
|
handle_errors(
|
||||||
|
&sess.parse_sess,
|
||||||
|
attr.span,
|
||||||
|
AttrError::MultipleStabilityLevels,
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut feature = None;
|
let mut feature = None;
|
||||||
|
@ -405,11 +423,16 @@ where
|
||||||
};
|
};
|
||||||
if sym::unstable == meta_name {
|
if sym::unstable == meta_name {
|
||||||
stab = Some((Stability { level, feature }, attr.span));
|
stab = Some((Stability { level, feature }, attr.span));
|
||||||
} else {
|
} else if sym::rustc_const_unstable == meta_name {
|
||||||
const_stab = Some((
|
const_stab = Some((
|
||||||
ConstStability { level, feature, promotable: false },
|
ConstStability { level, feature, promotable: false },
|
||||||
attr.span,
|
attr.span,
|
||||||
));
|
));
|
||||||
|
} else if sym::rustc_default_body_unstable == meta_name {
|
||||||
|
body_stab =
|
||||||
|
Some((DefaultBodyStability { level, feature }, attr.span));
|
||||||
|
} else {
|
||||||
|
unreachable!("Unknown stability attribute {meta_name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(None, _, _) => {
|
(None, _, _) => {
|
||||||
|
@ -542,7 +565,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(stab, const_stab)
|
(stab, const_stab, body_stab)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
|
pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
|
||||||
|
|
|
@ -520,6 +520,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
|
||||||
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
|
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
|
||||||
/// The caller is responsible for calling the access hooks!
|
/// The caller is responsible for calling the access hooks!
|
||||||
|
///
|
||||||
|
/// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead.
|
||||||
fn get_alloc_raw(
|
fn get_alloc_raw(
|
||||||
&self,
|
&self,
|
||||||
id: AllocId,
|
id: AllocId,
|
||||||
|
@ -589,6 +591,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
Ok(&self.get_alloc_raw(id)?.extra)
|
Ok(&self.get_alloc_raw(id)?.extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the `mutability` field of the given allocation.
|
||||||
|
pub fn get_alloc_mutability<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, Mutability> {
|
||||||
|
Ok(self.get_alloc_raw(id)?.mutability)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gives raw mutable access to the `Allocation`, without bounds or alignment checks.
|
/// Gives raw mutable access to the `Allocation`, without bounds or alignment checks.
|
||||||
/// The caller is responsible for calling the access hooks!
|
/// The caller is responsible for calling the access hooks!
|
||||||
///
|
///
|
||||||
|
|
|
@ -772,7 +772,7 @@ impl SyntaxExtension {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| (None, helper_attrs));
|
.unwrap_or_else(|| (None, helper_attrs));
|
||||||
let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
|
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
||||||
if let Some((_, sp)) = const_stability {
|
if let Some((_, sp)) = const_stability {
|
||||||
sess.parse_sess
|
sess.parse_sess
|
||||||
.span_diagnostic
|
.span_diagnostic
|
||||||
|
@ -784,6 +784,17 @@ impl SyntaxExtension {
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
if let Some((_, sp)) = body_stability {
|
||||||
|
sess.parse_sess
|
||||||
|
.span_diagnostic
|
||||||
|
.struct_span_err(sp, "macros cannot have body stability attributes")
|
||||||
|
.span_label(sp, "invalid body stability attribute")
|
||||||
|
.span_label(
|
||||||
|
sess.source_map().guess_head_span(span),
|
||||||
|
"body stability attribute affects this macro",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
SyntaxExtension {
|
SyntaxExtension {
|
||||||
kind,
|
kind,
|
||||||
|
|
|
@ -499,6 +499,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
),
|
),
|
||||||
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||||
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||||
|
ungated!(
|
||||||
|
rustc_default_body_unstable, Normal,
|
||||||
|
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
|
||||||
|
),
|
||||||
gated!(
|
gated!(
|
||||||
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
|
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
|
||||||
"allow_internal_unstable side-steps feature gating and stability checks",
|
"allow_internal_unstable side-steps feature gating and stability checks",
|
||||||
|
|
|
@ -207,6 +207,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||||
def_ident_span => { table }
|
def_ident_span => { table }
|
||||||
lookup_stability => { table }
|
lookup_stability => { table }
|
||||||
lookup_const_stability => { table }
|
lookup_const_stability => { table }
|
||||||
|
lookup_default_body_stability => { table }
|
||||||
lookup_deprecation_entry => { table }
|
lookup_deprecation_entry => { table }
|
||||||
visibility => { table }
|
visibility => { table }
|
||||||
unused_generic_params => { table }
|
unused_generic_params => { table }
|
||||||
|
|
|
@ -1029,6 +1029,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
if should_encode_stability(def_kind) {
|
if should_encode_stability(def_kind) {
|
||||||
self.encode_stability(def_id);
|
self.encode_stability(def_id);
|
||||||
self.encode_const_stability(def_id);
|
self.encode_const_stability(def_id);
|
||||||
|
self.encode_default_body_stability(def_id);
|
||||||
self.encode_deprecation(def_id);
|
self.encode_deprecation(def_id);
|
||||||
}
|
}
|
||||||
if should_encode_variances(def_kind) {
|
if should_encode_variances(def_kind) {
|
||||||
|
@ -1385,6 +1386,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_default_body_stability(&mut self, def_id: DefId) {
|
||||||
|
debug!("EncodeContext::encode_default_body_stability({:?})", def_id);
|
||||||
|
|
||||||
|
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
||||||
|
// the stability attributes are even enabled before using their queries.
|
||||||
|
if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
||||||
|
if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) {
|
||||||
|
record!(self.tables.lookup_default_body_stability[def_id] <- stab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_deprecation(&mut self, def_id: DefId) {
|
fn encode_deprecation(&mut self, def_id: DefId) {
|
||||||
debug!("EncodeContext::encode_deprecation({:?})", def_id);
|
debug!("EncodeContext::encode_deprecation({:?})", def_id);
|
||||||
if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
|
if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
|
||||||
|
|
|
@ -343,6 +343,7 @@ define_tables! {
|
||||||
def_ident_span: Table<DefIndex, LazyValue<Span>>,
|
def_ident_span: Table<DefIndex, LazyValue<Span>>,
|
||||||
lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
|
lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
|
||||||
lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
|
lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
|
||||||
|
lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>,
|
||||||
lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
|
lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
|
||||||
// As an optimization, a missing entry indicates an empty `&[]`.
|
// As an optimization, a missing entry indicates an empty `&[]`.
|
||||||
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
|
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub use self::StabilityLevel::*;
|
||||||
|
|
||||||
use crate::ty::{self, DefIdTree, TyCtxt};
|
use crate::ty::{self, DefIdTree, TyCtxt};
|
||||||
use rustc_ast::NodeId;
|
use rustc_ast::NodeId;
|
||||||
use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
|
use rustc_attr::{self as attr, ConstStability, DefaultBodyStability, Deprecation, Stability};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, Diagnostic};
|
use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_feature::GateIssue;
|
use rustc_feature::GateIssue;
|
||||||
|
@ -61,6 +61,7 @@ pub struct Index {
|
||||||
/// are filled by the annotator.
|
/// are filled by the annotator.
|
||||||
pub stab_map: FxHashMap<LocalDefId, Stability>,
|
pub stab_map: FxHashMap<LocalDefId, Stability>,
|
||||||
pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
|
pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
|
||||||
|
pub default_body_stab_map: FxHashMap<LocalDefId, DefaultBodyStability>,
|
||||||
pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
|
pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
|
||||||
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
|
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
|
||||||
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
|
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
|
||||||
|
@ -86,6 +87,10 @@ impl Index {
|
||||||
self.const_stab_map.get(&def_id).copied()
|
self.const_stab_map.get(&def_id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn local_default_body_stability(&self, def_id: LocalDefId) -> Option<DefaultBodyStability> {
|
||||||
|
self.default_body_stab_map.get(&def_id).copied()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn local_deprecation_entry(&self, def_id: LocalDefId) -> Option<DeprecationEntry> {
|
pub fn local_deprecation_entry(&self, def_id: LocalDefId) -> Option<DeprecationEntry> {
|
||||||
self.depr_map.get(&def_id).cloned()
|
self.depr_map.get(&def_id).cloned()
|
||||||
}
|
}
|
||||||
|
@ -416,6 +421,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
return EvalResult::Allow;
|
return EvalResult::Allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only the cross-crate scenario matters when checking unstable APIs
|
||||||
|
let cross_crate = !def_id.is_local();
|
||||||
|
if !cross_crate {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
let stability = self.lookup_stability(def_id);
|
let stability = self.lookup_stability(def_id);
|
||||||
debug!(
|
debug!(
|
||||||
"stability: \
|
"stability: \
|
||||||
|
@ -423,12 +434,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
def_id, span, stability
|
def_id, span, stability
|
||||||
);
|
);
|
||||||
|
|
||||||
// Only the cross-crate scenario matters when checking unstable APIs
|
|
||||||
let cross_crate = !def_id.is_local();
|
|
||||||
if !cross_crate {
|
|
||||||
return EvalResult::Allow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue #38412: private items lack stability markers.
|
// Issue #38412: private items lack stability markers.
|
||||||
if skip_stability_check_due_to_privacy(self, def_id) {
|
if skip_stability_check_due_to_privacy(self, def_id) {
|
||||||
return EvalResult::Allow;
|
return EvalResult::Allow;
|
||||||
|
@ -492,6 +497,62 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluates the default-impl stability of an item.
|
||||||
|
///
|
||||||
|
/// Returns `EvalResult::Allow` if the item's default implementation is stable, or unstable but the corresponding
|
||||||
|
/// `#![feature]` has been provided. Returns `EvalResult::Deny` which describes the offending
|
||||||
|
/// unstable feature otherwise.
|
||||||
|
pub fn eval_default_body_stability(self, def_id: DefId, span: Span) -> EvalResult {
|
||||||
|
let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
|
||||||
|
if !is_staged_api {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only the cross-crate scenario matters when checking unstable APIs
|
||||||
|
let cross_crate = !def_id.is_local();
|
||||||
|
if !cross_crate {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stability = self.lookup_default_body_stability(def_id);
|
||||||
|
debug!(
|
||||||
|
"body stability: inspecting def_id={def_id:?} span={span:?} of stability={stability:?}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Issue #38412: private items lack stability markers.
|
||||||
|
if skip_stability_check_due_to_privacy(self, def_id) {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
match stability {
|
||||||
|
Some(DefaultBodyStability {
|
||||||
|
level: attr::Unstable { reason, issue, is_soft, .. },
|
||||||
|
feature,
|
||||||
|
}) => {
|
||||||
|
if span.allows_unstable(feature) {
|
||||||
|
debug!("body stability: skipping span={:?} since it is internal", span);
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
if self.features().active(feature) {
|
||||||
|
return EvalResult::Allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvalResult::Deny {
|
||||||
|
feature,
|
||||||
|
reason: reason.to_opt_reason(),
|
||||||
|
issue,
|
||||||
|
suggestion: None,
|
||||||
|
is_soft,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
// Stable APIs are always ok to call
|
||||||
|
EvalResult::Allow
|
||||||
|
}
|
||||||
|
None => EvalResult::Unmarked,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if an item is stable or error out.
|
/// Checks if an item is stable or error out.
|
||||||
///
|
///
|
||||||
/// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
|
/// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
|
||||||
|
|
|
@ -80,6 +80,8 @@ macro_rules! make_mir_visitor {
|
||||||
self.super_body(body);
|
self.super_body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extra_body_methods!($($mutability)?);
|
||||||
|
|
||||||
fn visit_basic_block_data(
|
fn visit_basic_block_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
|
@ -287,63 +289,7 @@ macro_rules! make_mir_visitor {
|
||||||
&mut self,
|
&mut self,
|
||||||
body: &$($mutability)? Body<'tcx>,
|
body: &$($mutability)? Body<'tcx>,
|
||||||
) {
|
) {
|
||||||
let span = body.span;
|
super_body!(self, body, $($mutability, true)?);
|
||||||
if let Some(gen) = &$($mutability)? body.generator {
|
|
||||||
if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
|
|
||||||
self.visit_ty(
|
|
||||||
yield_ty,
|
|
||||||
TyContext::YieldTy(SourceInfo::outermost(span))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for best performance, we want to use an iterator rather
|
|
||||||
// than a for-loop, to avoid calling `body::Body::invalidate` for
|
|
||||||
// each basic block.
|
|
||||||
#[allow(unused_macro_rules)]
|
|
||||||
macro_rules! basic_blocks {
|
|
||||||
(mut) => (body.basic_blocks_mut().iter_enumerated_mut());
|
|
||||||
() => (body.basic_blocks().iter_enumerated());
|
|
||||||
}
|
|
||||||
for (bb, data) in basic_blocks!($($mutability)?) {
|
|
||||||
self.visit_basic_block_data(bb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for scope in &$($mutability)? body.source_scopes {
|
|
||||||
self.visit_source_scope_data(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.visit_ty(
|
|
||||||
$(& $mutability)? body.return_ty(),
|
|
||||||
TyContext::ReturnTy(SourceInfo::outermost(body.span))
|
|
||||||
);
|
|
||||||
|
|
||||||
for local in body.local_decls.indices() {
|
|
||||||
self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macro_rules)]
|
|
||||||
macro_rules! type_annotations {
|
|
||||||
(mut) => (body.user_type_annotations.iter_enumerated_mut());
|
|
||||||
() => (body.user_type_annotations.iter_enumerated());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index, annotation) in type_annotations!($($mutability)?) {
|
|
||||||
self.visit_user_type_annotation(
|
|
||||||
index, annotation
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for var_debug_info in &$($mutability)? body.var_debug_info {
|
|
||||||
self.visit_var_debug_info(var_debug_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.visit_span($(& $mutability)? body.span);
|
|
||||||
|
|
||||||
for const_ in &$($mutability)? body.required_consts {
|
|
||||||
let location = START_BLOCK.start_location();
|
|
||||||
self.visit_constant(const_, location);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_basic_block_data(&mut self,
|
fn super_basic_block_data(&mut self,
|
||||||
|
@ -982,12 +928,7 @@ macro_rules! make_mir_visitor {
|
||||||
body: &$($mutability)? Body<'tcx>,
|
body: &$($mutability)? Body<'tcx>,
|
||||||
location: Location
|
location: Location
|
||||||
) {
|
) {
|
||||||
#[allow(unused_macro_rules)]
|
let basic_block = & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
|
||||||
macro_rules! basic_blocks {
|
|
||||||
(mut) => (body.basic_blocks_mut());
|
|
||||||
() => (body.basic_blocks());
|
|
||||||
}
|
|
||||||
let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
|
|
||||||
if basic_block.statements.len() == location.statement_index {
|
if basic_block.statements.len() == location.statement_index {
|
||||||
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
|
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
|
||||||
self.visit_terminator(terminator, location)
|
self.visit_terminator(terminator, location)
|
||||||
|
@ -1002,6 +943,94 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! basic_blocks {
|
||||||
|
($body:ident, mut, true) => {
|
||||||
|
$body.basic_blocks.as_mut()
|
||||||
|
};
|
||||||
|
($body:ident, mut, false) => {
|
||||||
|
$body.basic_blocks.as_mut_preserves_cfg()
|
||||||
|
};
|
||||||
|
($body:ident,) => {
|
||||||
|
$body.basic_blocks()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! basic_blocks_iter {
|
||||||
|
($body:ident, mut, $invalidate:tt) => {
|
||||||
|
basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
|
||||||
|
};
|
||||||
|
($body:ident,) => {
|
||||||
|
basic_blocks!($body,).iter_enumerated()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! extra_body_methods {
|
||||||
|
(mut) => {
|
||||||
|
fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
|
||||||
|
self.super_body_preserves_cfg(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
|
||||||
|
super_body!(self, body, mut, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! super_body {
|
||||||
|
($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
|
||||||
|
let span = $body.span;
|
||||||
|
if let Some(gen) = &$($mutability)? $body.generator {
|
||||||
|
if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
|
||||||
|
$self.visit_ty(
|
||||||
|
yield_ty,
|
||||||
|
TyContext::YieldTy(SourceInfo::outermost(span))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
|
||||||
|
$self.visit_basic_block_data(bb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for scope in &$($mutability)? $body.source_scopes {
|
||||||
|
$self.visit_source_scope_data(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
$self.visit_ty(
|
||||||
|
$(& $mutability)? $body.return_ty(),
|
||||||
|
TyContext::ReturnTy(SourceInfo::outermost($body.span))
|
||||||
|
);
|
||||||
|
|
||||||
|
for local in $body.local_decls.indices() {
|
||||||
|
$self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macro_rules)]
|
||||||
|
macro_rules! type_annotations {
|
||||||
|
(mut) => ($body.user_type_annotations.iter_enumerated_mut());
|
||||||
|
() => ($body.user_type_annotations.iter_enumerated());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, annotation) in type_annotations!($($mutability)?) {
|
||||||
|
$self.visit_user_type_annotation(
|
||||||
|
index, annotation
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for var_debug_info in &$($mutability)? $body.var_debug_info {
|
||||||
|
$self.visit_var_debug_info(var_debug_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
$self.visit_span($(& $mutability)? $body.span);
|
||||||
|
|
||||||
|
for const_ in &$($mutability)? $body.required_consts {
|
||||||
|
let location = START_BLOCK.start_location();
|
||||||
|
$self.visit_constant(const_, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! visit_place_fns {
|
macro_rules! visit_place_fns {
|
||||||
(mut) => {
|
(mut) => {
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||||
|
|
|
@ -1094,6 +1094,11 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query lookup_default_body_stability(def_id: DefId) -> Option<attr::DefaultBodyStability> {
|
||||||
|
desc { |tcx| "looking up default body stability of `{}`", tcx.def_path_str(def_id) }
|
||||||
|
separate_provide_extern
|
||||||
|
}
|
||||||
|
|
||||||
query should_inherit_track_caller(def_id: DefId) -> bool {
|
query should_inherit_track_caller(def_id: DefId) -> bool {
|
||||||
desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
@ -1951,6 +1956,14 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query is_impossible_method(key: (DefId, DefId)) -> bool {
|
||||||
|
desc { |tcx|
|
||||||
|
"checking if {} is impossible to call within {}",
|
||||||
|
tcx.def_path_str(key.1),
|
||||||
|
tcx.def_path_str(key.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query method_autoderef_steps(
|
query method_autoderef_steps(
|
||||||
goal: CanonicalTyGoal<'tcx>
|
goal: CanonicalTyGoal<'tcx>
|
||||||
) -> MethodAutoderefStepsResult<'tcx> {
|
) -> MethodAutoderefStepsResult<'tcx> {
|
||||||
|
|
|
@ -64,6 +64,7 @@ trivially_parameterized_over_tcx! {
|
||||||
rustc_ast::Attribute,
|
rustc_ast::Attribute,
|
||||||
rustc_ast::MacArgs,
|
rustc_ast::MacArgs,
|
||||||
rustc_attr::ConstStability,
|
rustc_attr::ConstStability,
|
||||||
|
rustc_attr::DefaultBodyStability,
|
||||||
rustc_attr::Deprecation,
|
rustc_attr::Deprecation,
|
||||||
rustc_attr::Stability,
|
rustc_attr::Stability,
|
||||||
rustc_hir::Constness,
|
rustc_hir::Constness,
|
||||||
|
|
|
@ -849,22 +849,22 @@ fn non_exhaustive_match<'p, 'tcx>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
[.., prev, last] if prev.span.eq_ctxt(last.span) => {
|
[.., prev, last] if prev.span.eq_ctxt(last.span) => {
|
||||||
if let Ok(snippet) = sm.span_to_snippet(prev.span.between(last.span)) {
|
let comma = if matches!(last.body.kind, hir::ExprKind::Block(..))
|
||||||
let comma = if matches!(last.body.kind, hir::ExprKind::Block(..))
|
&& last.span.eq_ctxt(last.body.span)
|
||||||
&& last.span.eq_ctxt(last.body.span)
|
{
|
||||||
{
|
""
|
||||||
""
|
} else {
|
||||||
} else {
|
","
|
||||||
","
|
};
|
||||||
};
|
let spacing = if sm.is_multiline(prev.span.between(last.span)) {
|
||||||
|
sm.indentation_before(last.span).map(|indent| format!("\n{indent}"))
|
||||||
|
} else {
|
||||||
|
Some(" ".to_string())
|
||||||
|
};
|
||||||
|
if let Some(spacing) = spacing {
|
||||||
suggestion = Some((
|
suggestion = Some((
|
||||||
last.span.shrink_to_hi(),
|
last.span.shrink_to_hi(),
|
||||||
format!(
|
format!("{}{}{} => todo!()", comma, spacing, pattern),
|
||||||
"{}{}{} => todo!()",
|
|
||||||
comma,
|
|
||||||
snippet.strip_prefix(',').unwrap_or(&snippet),
|
|
||||||
pattern
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub struct DeleteNonCodegenStatements<'tcx> {
|
||||||
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
|
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let mut delete = DeleteNonCodegenStatements { tcx };
|
let mut delete = DeleteNonCodegenStatements { tcx };
|
||||||
delete.visit_body(body);
|
delete.visit_body_preserves_cfg(body);
|
||||||
body.user_type_annotations.raw.clear();
|
body.user_type_annotations.raw.clear();
|
||||||
|
|
||||||
for decl in &mut body.local_decls {
|
for decl in &mut body.local_decls {
|
||||||
|
|
|
@ -951,7 +951,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_body(&mut self, body: &mut Body<'tcx>) {
|
fn visit_body(&mut self, body: &mut Body<'tcx>) {
|
||||||
for (bb, data) in body.basic_blocks_mut().iter_enumerated_mut() {
|
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
|
||||||
self.visit_basic_block_data(bb, data);
|
self.visit_basic_block_data(bb, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let patch = MirPatch::new(body);
|
let patch = MirPatch::new(body);
|
||||||
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: body.local_decls.clone() };
|
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: body.local_decls.clone() };
|
||||||
|
|
||||||
for (bb, data) in body.basic_blocks_mut().iter_enumerated_mut() {
|
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
|
||||||
checker.visit_basic_block_data(bb, data);
|
checker.visit_basic_block_data(bb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
|
||||||
ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
|
ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
|
||||||
|
|
||||||
for (block, BasicBlockData { statements, terminator, .. }) in
|
for (block, BasicBlockData { statements, terminator, .. }) in
|
||||||
body.basic_blocks.as_mut().iter_enumerated_mut()
|
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut()
|
||||||
{
|
{
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
for statement in statements {
|
for statement in statements {
|
||||||
|
|
|
@ -53,10 +53,10 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
||||||
def_id, returned_local
|
def_id, returned_local
|
||||||
);
|
);
|
||||||
|
|
||||||
RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);
|
RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body_preserves_cfg(body);
|
||||||
|
|
||||||
// Clean up the `NOP`s we inserted for statements made useless by our renaming.
|
// Clean up the `NOP`s we inserted for statements made useless by our renaming.
|
||||||
for block_data in body.basic_blocks_mut() {
|
for block_data in body.basic_blocks.as_mut_preserves_cfg() {
|
||||||
block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
|
block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for RevealAll {
|
||||||
}
|
}
|
||||||
|
|
||||||
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
|
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
|
||||||
RevealAllVisitor { tcx, param_env }.visit_body(body);
|
RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,7 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
|
||||||
if map.iter().any(Option::is_none) {
|
if map.iter().any(Option::is_none) {
|
||||||
// Update references to all vars and tmps now
|
// Update references to all vars and tmps now
|
||||||
let mut updater = LocalUpdater { map, tcx };
|
let mut updater = LocalUpdater { map, tcx };
|
||||||
updater.visit_body(body);
|
updater.visit_body_preserves_cfg(body);
|
||||||
|
|
||||||
body.local_decls.shrink_to_fit();
|
body.local_decls.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>)
|
||||||
while modified {
|
while modified {
|
||||||
modified = false;
|
modified = false;
|
||||||
|
|
||||||
for data in body.basic_blocks_mut() {
|
for data in body.basic_blocks.as_mut_preserves_cfg() {
|
||||||
// Remove unnecessary StorageLive and StorageDead annotations.
|
// Remove unnecessary StorageLive and StorageDead annotations.
|
||||||
data.statements.retain(|statement| {
|
data.statements.retain(|statement| {
|
||||||
let keep = match &statement.kind {
|
let keep = match &statement.kind {
|
||||||
|
|
|
@ -29,11 +29,16 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
|
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
|
||||||
let stab_attrs =
|
let stab_attrs = [
|
||||||
[sym::stable, sym::unstable, sym::rustc_const_stable, sym::rustc_const_unstable];
|
sym::stable,
|
||||||
|
sym::unstable,
|
||||||
|
sym::rustc_const_stable,
|
||||||
|
sym::rustc_const_unstable,
|
||||||
|
sym::rustc_default_body_unstable,
|
||||||
|
];
|
||||||
|
|
||||||
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
|
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
|
||||||
// #[rustc_const_stable(…)], or #[rustc_const_unstable(…)].
|
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
|
||||||
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
|
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
|
||||||
let meta_kind = attr.meta_kind();
|
let meta_kind = attr.meta_kind();
|
||||||
if let Some(MetaItemKind::List(ref metas)) = meta_kind {
|
if let Some(MetaItemKind::List(ref metas)) = meta_kind {
|
||||||
|
@ -53,8 +58,12 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
||||||
// This additional check for stability is to make sure we
|
// This additional check for stability is to make sure we
|
||||||
// don't emit additional, irrelevant errors for malformed
|
// don't emit additional, irrelevant errors for malformed
|
||||||
// attributes.
|
// attributes.
|
||||||
let is_unstable =
|
let is_unstable = matches!(
|
||||||
matches!(*stab_attr, sym::unstable | sym::rustc_const_unstable);
|
*stab_attr,
|
||||||
|
sym::unstable
|
||||||
|
| sym::rustc_const_unstable
|
||||||
|
| sym::rustc_default_body_unstable
|
||||||
|
);
|
||||||
if since.is_some() || is_unstable {
|
if since.is_some() || is_unstable {
|
||||||
return Some((feature, since, attr.span));
|
return Some((feature, since, attr.span));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! Checks validity of naked functions.
|
//! Checks validity of naked functions.
|
||||||
|
|
||||||
use rustc_ast::{Attribute, InlineAsmOptions};
|
use rustc_ast::InlineAsmOptions;
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::{FnKind, Visitor};
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::{ExprKind, HirId, InlineAsmOperand, StmtKind};
|
use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
|
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
|
||||||
|
@ -13,71 +14,58 @@ use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
|
||||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckNakedFunctions { tcx });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { check_mod_naked_functions, ..*providers };
|
*providers = Providers { check_mod_naked_functions, ..*providers };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CheckNakedFunctions<'tcx> {
|
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||||
tcx: TyCtxt<'tcx>,
|
let items = tcx.hir_module_items(module_def_id);
|
||||||
}
|
for def_id in items.definitions() {
|
||||||
|
if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
|
||||||
impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
|
continue;
|
||||||
fn visit_fn(
|
|
||||||
&mut self,
|
|
||||||
fk: FnKind<'_>,
|
|
||||||
_fd: &'tcx hir::FnDecl<'tcx>,
|
|
||||||
body_id: hir::BodyId,
|
|
||||||
span: Span,
|
|
||||||
hir_id: HirId,
|
|
||||||
) {
|
|
||||||
let ident_span;
|
|
||||||
let fn_header;
|
|
||||||
|
|
||||||
match fk {
|
|
||||||
FnKind::Closure => {
|
|
||||||
// Closures with a naked attribute are rejected during attribute
|
|
||||||
// check. Don't validate them any further.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FnKind::ItemFn(ident, _, ref header, ..) => {
|
|
||||||
ident_span = ident.span;
|
|
||||||
fn_header = header;
|
|
||||||
}
|
|
||||||
|
|
||||||
FnKind::Method(ident, ref sig, ..) => {
|
|
||||||
ident_span = ident.span;
|
|
||||||
fn_header = &sig.header;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let attrs = self.tcx.hir().attrs(hir_id);
|
let naked = tcx.has_attr(def_id.to_def_id(), sym::naked);
|
||||||
let naked = attrs.iter().any(|attr| attr.has_name(sym::naked));
|
if !naked {
|
||||||
if naked {
|
continue;
|
||||||
let body = self.tcx.hir().body(body_id);
|
|
||||||
check_abi(self.tcx, hir_id, fn_header.abi, ident_span);
|
|
||||||
check_no_patterns(self.tcx, body.params);
|
|
||||||
check_no_parameters_use(self.tcx, body);
|
|
||||||
check_asm(self.tcx, body, span);
|
|
||||||
check_inline(self.tcx, attrs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (fn_header, body_id) = match tcx.hir().get_by_def_id(def_id) {
|
||||||
|
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })
|
||||||
|
| hir::Node::TraitItem(hir::TraitItem {
|
||||||
|
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| hir::Node::ImplItem(hir::ImplItem {
|
||||||
|
kind: hir::ImplItemKind::Fn(sig, body_id),
|
||||||
|
..
|
||||||
|
}) => (sig.header, *body_id),
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let body = tcx.hir().body(body_id);
|
||||||
|
check_abi(tcx, def_id, fn_header.abi);
|
||||||
|
check_no_patterns(tcx, body.params);
|
||||||
|
check_no_parameters_use(tcx, body);
|
||||||
|
check_asm(tcx, def_id, body);
|
||||||
|
check_inline(tcx, def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the function isn't inlined.
|
/// Check that the function isn't inlined.
|
||||||
fn check_inline(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
for attr in attrs.iter().filter(|attr| attr.has_name(sym::inline)) {
|
let attrs = tcx.get_attrs(def_id.to_def_id(), sym::inline);
|
||||||
|
for attr in attrs {
|
||||||
tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
|
tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that function uses non-Rust ABI.
|
/// Checks that function uses non-Rust ABI.
|
||||||
fn check_abi(tcx: TyCtxt<'_>, hir_id: HirId, abi: Abi, fn_ident_span: Span) {
|
fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
|
||||||
if abi == Abi::Rust {
|
if abi == Abi::Rust {
|
||||||
tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, fn_ident_span, |lint| {
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
let span = tcx.def_span(def_id);
|
||||||
|
tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
|
||||||
lint.build("Rust ABI is unsupported in naked functions").emit();
|
lint.build("Rust ABI is unsupported in naked functions").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -141,7 +129,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that function body contains a single inline assembly block.
|
/// Checks that function body contains a single inline assembly block.
|
||||||
fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
|
fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) {
|
||||||
let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
|
let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
|
||||||
this.visit_body(body);
|
this.visit_body(body);
|
||||||
if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
|
if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
|
||||||
|
@ -149,7 +137,7 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>, fn_span: Span
|
||||||
} else {
|
} else {
|
||||||
let mut diag = struct_span_err!(
|
let mut diag = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
fn_span,
|
tcx.def_span(def_id),
|
||||||
E0787,
|
E0787,
|
||||||
"naked functions must contain a single asm block"
|
"naked functions must contain a single asm block"
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! A pass that annotates every item and method with its stability level,
|
//! A pass that annotates every item and method with its stability level,
|
||||||
//! propagating default levels lexically from parent to children ast nodes.
|
//! propagating default levels lexically from parent to children ast nodes.
|
||||||
|
|
||||||
use attr::StabilityLevel;
|
use rustc_attr::{
|
||||||
use rustc_attr::{self as attr, ConstStability, Stability, Unstable, UnstableReason};
|
self as attr, ConstStability, Stability, StabilityLevel, Unstable, UnstableReason,
|
||||||
|
};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -161,7 +162,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
let (stab, const_stab, body_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
||||||
let mut const_span = None;
|
let mut const_span = None;
|
||||||
|
|
||||||
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
|
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
|
||||||
|
@ -209,6 +210,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some((body_stab, _span)) = body_stab {
|
||||||
|
// FIXME: check that this item can have body stability
|
||||||
|
|
||||||
|
self.index.default_body_stab_map.insert(def_id, body_stab);
|
||||||
|
debug!(?self.index.default_body_stab_map);
|
||||||
|
}
|
||||||
|
|
||||||
let stab = stab.map(|(stab, span)| {
|
let stab = stab.map(|(stab, span)| {
|
||||||
// Error if prohibited, or can't inherit anything from a container.
|
// Error if prohibited, or can't inherit anything from a container.
|
||||||
if kind == AnnotationKind::Prohibited
|
if kind == AnnotationKind::Prohibited
|
||||||
|
@ -613,6 +621,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
||||||
let mut index = Index {
|
let mut index = Index {
|
||||||
stab_map: Default::default(),
|
stab_map: Default::default(),
|
||||||
const_stab_map: Default::default(),
|
const_stab_map: Default::default(),
|
||||||
|
default_body_stab_map: Default::default(),
|
||||||
depr_map: Default::default(),
|
depr_map: Default::default(),
|
||||||
implications: Default::default(),
|
implications: Default::default(),
|
||||||
};
|
};
|
||||||
|
@ -673,6 +682,9 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
stability_implications: |tcx, _| tcx.stability().implications.clone(),
|
stability_implications: |tcx, _| tcx.stability().implications.clone(),
|
||||||
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
|
lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
|
||||||
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
|
lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
|
||||||
|
lookup_default_body_stability: |tcx, id| {
|
||||||
|
tcx.stability().local_default_body_stability(id.expect_local())
|
||||||
|
},
|
||||||
lookup_deprecation_entry: |tcx, id| {
|
lookup_deprecation_entry: |tcx, id| {
|
||||||
tcx.stability().local_deprecation_entry(id.expect_local())
|
tcx.stability().local_deprecation_entry(id.expect_local())
|
||||||
},
|
},
|
||||||
|
@ -723,7 +735,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.staged_api {
|
if features.staged_api {
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||||
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item.span);
|
let (stab, const_stab, _) =
|
||||||
|
attr::find_stability(&self.tcx.sess, attrs, item.span);
|
||||||
|
|
||||||
// If this impl block has an #[unstable] attribute, give an
|
// If this impl block has an #[unstable] attribute, give an
|
||||||
// error if all involved types and traits are stable, because
|
// error if all involved types and traits are stable, because
|
||||||
|
|
|
@ -2544,12 +2544,15 @@ fn show_candidates(
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
if let [first, .., last] = &path[..] {
|
if let [first, .., last] = &path[..] {
|
||||||
err.span_suggestion_verbose(
|
let sp = first.ident.span.until(last.ident.span);
|
||||||
first.ident.span.until(last.ident.span),
|
if sp.can_be_used_for_suggestions() {
|
||||||
&format!("if you import `{}`, refer to it directly", last.ident),
|
err.span_suggestion_verbose(
|
||||||
"",
|
sp,
|
||||||
Applicability::Unspecified,
|
&format!("if you import `{}`, refer to it directly", last.ident),
|
||||||
);
|
"",
|
||||||
|
Applicability::Unspecified,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.push(':');
|
msg.push(':');
|
||||||
|
|
|
@ -1218,6 +1218,7 @@ symbols! {
|
||||||
rustc_conversion_suggestion,
|
rustc_conversion_suggestion,
|
||||||
rustc_deallocator,
|
rustc_deallocator,
|
||||||
rustc_def_path,
|
rustc_def_path,
|
||||||
|
rustc_default_body_unstable,
|
||||||
rustc_diagnostic_item,
|
rustc_diagnostic_item,
|
||||||
rustc_diagnostic_macros,
|
rustc_diagnostic_macros,
|
||||||
rustc_dirty,
|
rustc_dirty,
|
||||||
|
|
|
@ -1315,6 +1315,13 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
|
||||||
error: &MismatchedProjectionTypes<'tcx>,
|
error: &MismatchedProjectionTypes<'tcx>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn maybe_detailed_projection_msg(
|
||||||
|
&self,
|
||||||
|
pred: ty::ProjectionPredicate<'tcx>,
|
||||||
|
normalized_ty: ty::Term<'tcx>,
|
||||||
|
expected_ty: ty::Term<'tcx>,
|
||||||
|
) -> Option<String>;
|
||||||
|
|
||||||
fn fuzzy_match_tys(
|
fn fuzzy_match_tys(
|
||||||
&self,
|
&self,
|
||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
|
@ -1542,23 +1549,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
normalized_ty,
|
normalized_ty,
|
||||||
data.term,
|
data.term,
|
||||||
) {
|
) {
|
||||||
values = Some(infer::ValuePairs::Terms(ExpectedFound::new(
|
values = Some((data, is_normalized_ty_expected, normalized_ty, data.term));
|
||||||
is_normalized_ty_expected,
|
|
||||||
normalized_ty,
|
|
||||||
data.term,
|
|
||||||
)));
|
|
||||||
err_buf = error;
|
err_buf = error;
|
||||||
err = &err_buf;
|
err = &err_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diag = struct_span_err!(
|
let msg = values
|
||||||
self.tcx.sess,
|
.and_then(|(predicate, _, normalized_ty, expected_ty)| {
|
||||||
obligation.cause.span,
|
self.maybe_detailed_projection_msg(predicate, normalized_ty, expected_ty)
|
||||||
E0271,
|
})
|
||||||
"type mismatch resolving `{}`",
|
.unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
|
||||||
predicate
|
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
|
||||||
);
|
|
||||||
let secondary_span = match predicate.kind().skip_binder() {
|
let secondary_span = match predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::Projection(proj) => self
|
ty::PredicateKind::Projection(proj) => self
|
||||||
.tcx
|
.tcx
|
||||||
|
@ -1596,7 +1599,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
&mut diag,
|
&mut diag,
|
||||||
&obligation.cause,
|
&obligation.cause,
|
||||||
secondary_span,
|
secondary_span,
|
||||||
values,
|
values.map(|(_, is_normalized_ty_expected, normalized_ty, term)| {
|
||||||
|
infer::ValuePairs::Terms(ExpectedFound::new(
|
||||||
|
is_normalized_ty_expected,
|
||||||
|
normalized_ty,
|
||||||
|
term,
|
||||||
|
))
|
||||||
|
}),
|
||||||
err,
|
err,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
@ -1606,6 +1615,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maybe_detailed_projection_msg(
|
||||||
|
&self,
|
||||||
|
pred: ty::ProjectionPredicate<'tcx>,
|
||||||
|
normalized_ty: ty::Term<'tcx>,
|
||||||
|
expected_ty: ty::Term<'tcx>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
|
||||||
|
let self_ty = pred.projection_ty.self_ty();
|
||||||
|
|
||||||
|
if Some(pred.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() {
|
||||||
|
Some(format!(
|
||||||
|
"expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
|
||||||
|
fn_kind = self_ty.prefix_string(self.tcx)
|
||||||
|
))
|
||||||
|
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
|
||||||
|
Some(format!(
|
||||||
|
"expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
|
||||||
|
))
|
||||||
|
} else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
|
||||||
|
Some(format!(
|
||||||
|
"expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fuzzy_match_tys(
|
fn fuzzy_match_tys(
|
||||||
&self,
|
&self,
|
||||||
mut a: Ty<'tcx>,
|
mut a: Ty<'tcx>,
|
||||||
|
|
|
@ -34,7 +34,10 @@ use rustc_infer::traits::TraitEngineExt as _;
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
||||||
use rustc_middle::ty::visit::TypeVisitable;
|
use rustc_middle::ty::visit::TypeVisitable;
|
||||||
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
|
use rustc_middle::ty::{
|
||||||
|
self, DefIdTree, GenericParamDefKind, Subst, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
|
||||||
|
VtblEntry,
|
||||||
|
};
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::{sym, Span};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -503,6 +506,77 @@ fn subst_and_check_impossible_predicates<'tcx>(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether a trait's method is impossible to call on a given impl.
|
||||||
|
///
|
||||||
|
/// This only considers predicates that reference the impl's generics, and not
|
||||||
|
/// those that reference the method's generics.
|
||||||
|
fn is_impossible_method<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
(impl_def_id, trait_item_def_id): (DefId, DefId),
|
||||||
|
) -> bool {
|
||||||
|
struct ReferencesOnlyParentGenerics<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
generics: &'tcx ty::Generics,
|
||||||
|
trait_item_def_id: DefId,
|
||||||
|
}
|
||||||
|
impl<'tcx> ty::TypeVisitor<'tcx> for ReferencesOnlyParentGenerics<'tcx> {
|
||||||
|
type BreakTy = ();
|
||||||
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
// If this is a parameter from the trait item's own generics, then bail
|
||||||
|
if let ty::Param(param) = t.kind()
|
||||||
|
&& let param_def_id = self.generics.type_param(param, self.tcx).def_id
|
||||||
|
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
|
||||||
|
{
|
||||||
|
return ControlFlow::BREAK;
|
||||||
|
}
|
||||||
|
t.super_visit_with(self)
|
||||||
|
}
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if let ty::ReEarlyBound(param) = r.kind()
|
||||||
|
&& let param_def_id = self.generics.region_param(¶m, self.tcx).def_id
|
||||||
|
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
|
||||||
|
{
|
||||||
|
return ControlFlow::BREAK;
|
||||||
|
}
|
||||||
|
r.super_visit_with(self)
|
||||||
|
}
|
||||||
|
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if let ty::ConstKind::Param(param) = ct.kind()
|
||||||
|
&& let param_def_id = self.generics.const_param(¶m, self.tcx).def_id
|
||||||
|
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
|
||||||
|
{
|
||||||
|
return ControlFlow::BREAK;
|
||||||
|
}
|
||||||
|
ct.super_visit_with(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let generics = tcx.generics_of(trait_item_def_id);
|
||||||
|
let predicates = tcx.predicates_of(trait_item_def_id);
|
||||||
|
let impl_trait_ref =
|
||||||
|
tcx.impl_trait_ref(impl_def_id).expect("expected impl to correspond to trait");
|
||||||
|
let param_env = tcx.param_env(impl_def_id);
|
||||||
|
|
||||||
|
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
|
||||||
|
let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
|
||||||
|
if pred.visit_with(&mut visitor).is_continue() {
|
||||||
|
Some(Obligation::new(
|
||||||
|
ObligationCause::dummy_with_span(*span),
|
||||||
|
param_env,
|
||||||
|
ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tcx.infer_ctxt().ignoring_regions().enter(|ref infcx| {
|
||||||
|
let mut fulfill_ctxt = <dyn TraitEngine<'_>>::new(tcx);
|
||||||
|
fulfill_ctxt.register_predicate_obligations(infcx, predicates_for_trait);
|
||||||
|
!fulfill_ctxt.select_all_or_error(infcx).is_empty()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum VtblSegment<'tcx> {
|
enum VtblSegment<'tcx> {
|
||||||
MetadataDSA,
|
MetadataDSA,
|
||||||
|
@ -883,6 +957,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
vtable_entries,
|
vtable_entries,
|
||||||
vtable_trait_upcasting_coercion_new_vptr_slot,
|
vtable_trait_upcasting_coercion_new_vptr_slot,
|
||||||
subst_and_check_impossible_predicates,
|
subst_and_check_impossible_predicates,
|
||||||
|
is_impossible_method,
|
||||||
try_unify_abstract_consts: |tcx, param_env_and| {
|
try_unify_abstract_consts: |tcx, param_env_and| {
|
||||||
let (param_env, (a, b)) = param_env_and.into_parts();
|
let (param_env, (a, b)) = param_env_and.into_parts();
|
||||||
const_evaluatable::try_unify_abstract_consts(tcx, (a, b), param_env)
|
const_evaluatable::try_unify_abstract_consts(tcx, (a, b), param_env)
|
||||||
|
|
|
@ -30,3 +30,4 @@ rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||||
rustc_lint = { path = "../rustc_lint" }
|
rustc_lint = { path = "../rustc_lint" }
|
||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||||
|
rustc_feature = { path = "../rustc_feature" }
|
||||||
|
|
|
@ -18,6 +18,7 @@ use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::Obligation;
|
use rustc_infer::traits::Obligation;
|
||||||
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
|
use rustc_middle::middle::stability::EvalResult;
|
||||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||||
|
@ -32,7 +33,6 @@ use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||||
use rustc_ty_utils::representability::{self, Representability};
|
use rustc_ty_utils::representability::{self, Representability};
|
||||||
|
|
||||||
use std::iter;
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
|
pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
|
||||||
|
@ -1104,12 +1104,28 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
missing_items.push(tcx.associated_item(trait_item_id));
|
missing_items.push(tcx.associated_item(trait_item_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(required_items) = &must_implement_one_of {
|
// true if this item is specifically implemented in this impl
|
||||||
// true if this item is specifically implemented in this impl
|
let is_implemented_here = ancestors
|
||||||
let is_implemented_here = ancestors
|
.leaf_def(tcx, trait_item_id)
|
||||||
.leaf_def(tcx, trait_item_id)
|
.map_or(false, |node_item| !node_item.defining_node.is_from_trait());
|
||||||
.map_or(false, |node_item| !node_item.defining_node.is_from_trait());
|
|
||||||
|
|
||||||
|
if !is_implemented_here {
|
||||||
|
match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
|
||||||
|
EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
|
||||||
|
tcx,
|
||||||
|
full_impl_span,
|
||||||
|
trait_item_id,
|
||||||
|
feature,
|
||||||
|
reason,
|
||||||
|
issue,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Unmarked default bodies are considered stable (at least for now).
|
||||||
|
EvalResult::Allow | EvalResult::Unmarked => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(required_items) = &must_implement_one_of {
|
||||||
if is_implemented_here {
|
if is_implemented_here {
|
||||||
let trait_item = tcx.associated_item(trait_item_id);
|
let trait_item = tcx.associated_item(trait_item_id);
|
||||||
if required_items.contains(&trait_item.ident(tcx)) {
|
if required_items.contains(&trait_item.ident(tcx)) {
|
||||||
|
@ -1494,76 +1510,109 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
|
detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp);
|
||||||
// This tracks the previous variant span (in the loop) incase we need it for diagnostics
|
|
||||||
let mut prev_variant_span: Span = DUMMY_SP;
|
|
||||||
for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) {
|
|
||||||
// Check for duplicate discriminant values
|
|
||||||
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
|
|
||||||
let variant_did = def.variant(VariantIdx::new(i)).def_id;
|
|
||||||
let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
|
|
||||||
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
|
|
||||||
let i_span = match variant_i.disr_expr {
|
|
||||||
Some(ref expr) => tcx.hir().span(expr.hir_id),
|
|
||||||
None => tcx.def_span(variant_did),
|
|
||||||
};
|
|
||||||
let span = match v.disr_expr {
|
|
||||||
Some(ref expr) => tcx.hir().span(expr.hir_id),
|
|
||||||
None => v.span,
|
|
||||||
};
|
|
||||||
let display_discr = format_discriminant_overflow(tcx, v, discr);
|
|
||||||
let display_discr_i = format_discriminant_overflow(tcx, variant_i, disr_vals[i]);
|
|
||||||
let no_disr = v.disr_expr.is_none();
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
sp,
|
|
||||||
E0081,
|
|
||||||
"discriminant value `{}` assigned more than once",
|
|
||||||
discr,
|
|
||||||
);
|
|
||||||
|
|
||||||
err.span_label(i_span, format!("first assignment of {display_discr_i}"));
|
|
||||||
err.span_label(span, format!("second assignment of {display_discr}"));
|
|
||||||
|
|
||||||
if no_disr {
|
|
||||||
err.span_label(
|
|
||||||
prev_variant_span,
|
|
||||||
format!(
|
|
||||||
"assigned discriminant for `{}` was incremented from this discriminant",
|
|
||||||
v.ident
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
disr_vals.push(discr);
|
|
||||||
prev_variant_span = v.span;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_representable(tcx, sp, def_id);
|
check_representable(tcx, sp, def_id);
|
||||||
check_transparent(tcx, sp, def);
|
check_transparent(tcx, sp, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the case that a discriminant is both a duplicate and an overflowing literal,
|
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
|
||||||
/// we insert both the assigned discriminant and the literal it overflowed from into the formatted
|
fn detect_discriminant_duplicate<'tcx>(
|
||||||
/// output. Otherwise we format the discriminant normally.
|
|
||||||
fn format_discriminant_overflow<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
variant: &hir::Variant<'_>,
|
mut discrs: Vec<(VariantIdx, Discr<'tcx>)>,
|
||||||
dis: Discr<'tcx>,
|
vs: &'tcx [hir::Variant<'tcx>],
|
||||||
) -> String {
|
self_span: Span,
|
||||||
if let Some(expr) = &variant.disr_expr {
|
) {
|
||||||
let body = &tcx.hir().body(expr.body).value;
|
// Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
|
||||||
if let hir::ExprKind::Lit(lit) = &body.kind
|
// Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
|
||||||
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
|
let report = |dis: Discr<'tcx>,
|
||||||
&& dis.val != *lit_value
|
idx: usize,
|
||||||
{
|
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>| {
|
||||||
return format!("`{dis}` (overflowed from `{lit_value}`)");
|
let var = &vs[idx]; // HIR for the duplicate discriminant
|
||||||
}
|
let (span, display_discr) = match var.disr_expr {
|
||||||
}
|
Some(ref expr) => {
|
||||||
|
// In the case the discriminant is both a duplicate and overflowed, let the user know
|
||||||
|
if let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
|
||||||
|
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
|
||||||
|
&& *lit_value != dis.val
|
||||||
|
{
|
||||||
|
(tcx.hir().span(expr.hir_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
|
||||||
|
// Otherwise, format the value as-is
|
||||||
|
} else {
|
||||||
|
(tcx.hir().span(expr.hir_id), format!("`{dis}`"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// At this point we know this discriminant is a duplicate, and was not explicitly
|
||||||
|
// assigned by the user. Here we iterate backwards to fetch the HIR for the last
|
||||||
|
// explictly assigned discriminant, and letting the user know that this was the
|
||||||
|
// increment startpoint, and how many steps from there leading to the duplicate
|
||||||
|
if let Some((n, hir::Variant { span, ident, .. })) =
|
||||||
|
vs[..idx].iter().rev().enumerate().find(|v| v.1.disr_expr.is_some())
|
||||||
|
{
|
||||||
|
let ve_ident = var.ident;
|
||||||
|
let n = n + 1;
|
||||||
|
let sp = if n > 1 { "variants" } else { "variant" };
|
||||||
|
|
||||||
format!("`{dis}`")
|
err.span_label(
|
||||||
|
*span,
|
||||||
|
format!("discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(vs[idx].span, format!("`{dis}`"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
err.span_label(span, format!("{display_discr} assigned here"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Here we loop through the discriminants, comparing each discriminant to another.
|
||||||
|
// When a duplicate is detected, we instatiate an error and point to both
|
||||||
|
// initial and duplicate value. The duplicate discriminant is then discarded by swapping
|
||||||
|
// it with the last element and decrementing the `vec.len` (which is why we have to evaluate
|
||||||
|
// `discrs.len()` anew every iteration, and why this could be tricky to do in a functional
|
||||||
|
// style as we are mutating `discrs` on the fly).
|
||||||
|
let mut i = 0;
|
||||||
|
while i < discrs.len() {
|
||||||
|
let hir_var_i_idx = discrs[i].0.index();
|
||||||
|
let mut error: Option<DiagnosticBuilder<'_, _>> = None;
|
||||||
|
|
||||||
|
let mut o = i + 1;
|
||||||
|
while o < discrs.len() {
|
||||||
|
let hir_var_o_idx = discrs[o].0.index();
|
||||||
|
|
||||||
|
if discrs[i].1.val == discrs[o].1.val {
|
||||||
|
let err = error.get_or_insert_with(|| {
|
||||||
|
let mut ret = struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
self_span,
|
||||||
|
E0081,
|
||||||
|
"discriminant value `{}` assigned more than once",
|
||||||
|
discrs[i].1,
|
||||||
|
);
|
||||||
|
|
||||||
|
report(discrs[i].1, hir_var_i_idx, &mut ret);
|
||||||
|
|
||||||
|
ret
|
||||||
|
});
|
||||||
|
|
||||||
|
report(discrs[o].1, hir_var_o_idx, err);
|
||||||
|
|
||||||
|
// Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
|
||||||
|
discrs[o] = *discrs.last().unwrap();
|
||||||
|
discrs.pop();
|
||||||
|
} else {
|
||||||
|
o += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut e) = error {
|
||||||
|
e.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn check_type_params_are_used<'tcx>(
|
pub(super) fn check_type_params_are_used<'tcx>(
|
||||||
|
|
|
@ -1589,11 +1589,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
) {
|
) {
|
||||||
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return;};
|
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return;};
|
||||||
let mut span: MultiSpan = vec![loop_span].into();
|
let mut span: MultiSpan = vec![loop_span].into();
|
||||||
span.push_span_label(loop_span, "this might have zero elements to iterate on".to_string());
|
span.push_span_label(loop_span, "this might have zero elements to iterate on");
|
||||||
for ret_expr in ret_exprs {
|
for ret_expr in ret_exprs {
|
||||||
span.push_span_label(
|
span.push_span_label(
|
||||||
ret_expr.span,
|
ret_expr.span,
|
||||||
"if the loop doesn't execute, this value would never get returned".to_string(),
|
"if the loop doesn't execute, this value would never get returned",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.span_note(
|
err.span_note(
|
||||||
|
|
|
@ -50,7 +50,6 @@ use rustc_span::hygiene::DesugaringKind;
|
||||||
use rustc_span::lev_distance::find_best_match_for_name;
|
use rustc_span::lev_distance::find_best_match_for_name;
|
||||||
use rustc_span::source_map::{Span, Spanned};
|
use rustc_span::source_map::{Span, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, Pos};
|
|
||||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||||
|
@ -2398,37 +2397,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
expr,
|
expr,
|
||||||
Some(span),
|
Some(span),
|
||||||
);
|
);
|
||||||
|
} else if let ty::RawPtr(ty_and_mut) = expr_t.kind()
|
||||||
|
&& let ty::Adt(adt_def, _) = ty_and_mut.ty.kind()
|
||||||
|
&& let ExprKind::Field(base_expr, _) = expr.kind
|
||||||
|
&& adt_def.variants().len() == 1
|
||||||
|
&& adt_def
|
||||||
|
.variants()
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.any(|f| f.ident(self.tcx) == field)
|
||||||
|
{
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"to access the field, dereference first",
|
||||||
|
vec![
|
||||||
|
(base_expr.span.shrink_to_lo(), "(*".to_string()),
|
||||||
|
(base_expr.span.shrink_to_hi(), ")".to_string()),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let mut found = false;
|
err.help("methods are immutable and cannot be assigned to");
|
||||||
|
|
||||||
if let ty::RawPtr(ty_and_mut) = expr_t.kind()
|
|
||||||
&& let ty::Adt(adt_def, _) = ty_and_mut.ty.kind()
|
|
||||||
{
|
|
||||||
if adt_def.variants().len() == 1
|
|
||||||
&& adt_def
|
|
||||||
.variants()
|
|
||||||
.iter()
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.any(|f| f.ident(self.tcx) == field)
|
|
||||||
{
|
|
||||||
if let Some(dot_loc) = expr_snippet.rfind('.') {
|
|
||||||
found = true;
|
|
||||||
err.span_suggestion(
|
|
||||||
expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)),
|
|
||||||
"to access the field, dereference first",
|
|
||||||
format!("(*{})", &expr_snippet[0..dot_loc]),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
err.help("methods are immutable and cannot be assigned to");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
|
|
|
@ -112,7 +112,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
|
use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::Idx;
|
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||||
|
@ -122,13 +121,14 @@ use rustc_session::parse::feature_err;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::DUMMY_SP;
|
use rustc_span::source_map::DUMMY_SP;
|
||||||
use rustc_span::symbol::{kw, Ident};
|
use rustc_span::symbol::{kw, Ident};
|
||||||
use rustc_span::{self, BytePos, Span};
|
use rustc_span::{self, BytePos, Span, Symbol};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
|
use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use crate::require_c_abi_if_c_variadic;
|
use crate::require_c_abi_if_c_variadic;
|
||||||
use crate::util::common::indenter;
|
use crate::util::common::indenter;
|
||||||
|
@ -662,6 +662,37 @@ fn missing_items_must_implement_one_of_err(
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_body_is_unstable(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
impl_span: Span,
|
||||||
|
item_did: DefId,
|
||||||
|
feature: Symbol,
|
||||||
|
reason: Option<Symbol>,
|
||||||
|
issue: Option<NonZeroU32>,
|
||||||
|
) {
|
||||||
|
let missing_item_name = &tcx.associated_item(item_did).name;
|
||||||
|
let use_of_unstable_library_feature_note = match reason {
|
||||||
|
Some(r) => format!("use of unstable library feature '{feature}': {r}"),
|
||||||
|
None => format!("use of unstable library feature '{feature}'"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
impl_span,
|
||||||
|
E0046,
|
||||||
|
"not all trait items implemented, missing: `{missing_item_name}`",
|
||||||
|
);
|
||||||
|
err.note(format!("default implementation of `{missing_item_name}` is unstable"));
|
||||||
|
err.note(use_of_unstable_library_feature_note);
|
||||||
|
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||||
|
&mut err,
|
||||||
|
&tcx.sess.parse_sess,
|
||||||
|
feature,
|
||||||
|
rustc_feature::GateIssue::Library(issue),
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
|
||||||
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
|
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
|
||||||
fn bounds_from_generic_predicates<'tcx>(
|
fn bounds_from_generic_predicates<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
|
@ -318,19 +318,11 @@ impl Duration {
|
||||||
/// assert_eq!(duration.as_secs(), 5);
|
/// assert_eq!(duration.as_secs(), 5);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// To determine the total number of seconds represented by the `Duration`,
|
/// To determine the total number of seconds represented by the `Duration`
|
||||||
/// use `as_secs` in combination with [`subsec_nanos`]:
|
/// including the fractional part, use [`as_secs_f64`] or [`as_secs_f32`]
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::time::Duration;
|
|
||||||
///
|
|
||||||
/// let duration = Duration::new(5, 730023852);
|
|
||||||
///
|
|
||||||
/// assert_eq!(5.730023852,
|
|
||||||
/// duration.as_secs() as f64
|
|
||||||
/// + duration.subsec_nanos() as f64 * 1e-9);
|
|
||||||
/// ```
|
|
||||||
///
|
///
|
||||||
|
/// [`as_secs_f32`]: Duration::as_secs_f64
|
||||||
|
/// [`as_secs_f64`]: Duration::as_secs_f32
|
||||||
/// [`subsec_nanos`]: Duration::subsec_nanos
|
/// [`subsec_nanos`]: Duration::subsec_nanos
|
||||||
#[stable(feature = "duration", since = "1.3.0")]
|
#[stable(feature = "duration", since = "1.3.0")]
|
||||||
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
|
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
|
||||||
|
|
|
@ -628,6 +628,10 @@ impl Step for Miri {
|
||||||
cargo.env("MIRI_HOST_SYSROOT", sysroot);
|
cargo.env("MIRI_HOST_SYSROOT", sysroot);
|
||||||
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
|
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
|
||||||
cargo.env("MIRI", miri);
|
cargo.env("MIRI", miri);
|
||||||
|
// propagate --bless
|
||||||
|
if builder.config.cmd.bless() {
|
||||||
|
cargo.env("MIRI_BLESS", "Gesundheit");
|
||||||
|
}
|
||||||
|
|
||||||
cargo.arg("--").args(builder.config.cmd.test_args());
|
cargo.arg("--").args(builder.config.cmd.test_args());
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,8 @@ def check_type(ty):
|
||||||
for bound in binding["binding"]["constraint"]:
|
for bound in binding["binding"]["constraint"]:
|
||||||
check_generic_bound(bound)
|
check_generic_bound(bound)
|
||||||
elif "parenthesized" in args:
|
elif "parenthesized" in args:
|
||||||
for ty in args["parenthesized"]["inputs"]:
|
for input_ty in args["parenthesized"]["inputs"]:
|
||||||
check_type(ty)
|
check_type(input_ty)
|
||||||
if args["parenthesized"]["output"]:
|
if args["parenthesized"]["output"]:
|
||||||
check_type(args["parenthesized"]["output"])
|
check_type(args["parenthesized"]["output"])
|
||||||
if not valid_id(ty["inner"]["id"]):
|
if not valid_id(ty["inner"]["id"]):
|
||||||
|
|
|
@ -348,15 +348,13 @@ where
|
||||||
fn make_final_bounds(
|
fn make_final_bounds(
|
||||||
&self,
|
&self,
|
||||||
ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
|
ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
|
||||||
ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)>,
|
ty_to_fn: FxHashMap<Type, (PolyTrait, Option<Type>)>,
|
||||||
lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>,
|
lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>,
|
||||||
) -> Vec<WherePredicate> {
|
) -> Vec<WherePredicate> {
|
||||||
ty_to_bounds
|
ty_to_bounds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|(ty, mut bounds)| {
|
.flat_map(|(ty, mut bounds)| {
|
||||||
if let Some(data) = ty_to_fn.get(&ty) {
|
if let Some((ref poly_trait, ref output)) = ty_to_fn.get(&ty) {
|
||||||
let (poly_trait, output) =
|
|
||||||
(data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
|
|
||||||
let mut new_path = poly_trait.trait_.clone();
|
let mut new_path = poly_trait.trait_.clone();
|
||||||
let last_segment = new_path.segments.pop().expect("segments were empty");
|
let last_segment = new_path.segments.pop().expect("segments were empty");
|
||||||
|
|
||||||
|
@ -374,8 +372,9 @@ where
|
||||||
GenericArgs::Parenthesized { inputs, output } => (inputs, output),
|
GenericArgs::Parenthesized { inputs, output } => (inputs, output),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let output = output.as_ref().cloned().map(Box::new);
|
||||||
if old_output.is_some() && old_output != output {
|
if old_output.is_some() && old_output != output {
|
||||||
panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1);
|
panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
|
let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
|
||||||
|
@ -385,7 +384,10 @@ where
|
||||||
.push(PathSegment { name: last_segment.name, args: new_params });
|
.push(PathSegment { name: last_segment.name, args: new_params });
|
||||||
|
|
||||||
bounds.insert(GenericBound::TraitBound(
|
bounds.insert(GenericBound::TraitBound(
|
||||||
PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params },
|
PolyTrait {
|
||||||
|
trait_: new_path,
|
||||||
|
generic_params: poly_trait.generic_params.clone(),
|
||||||
|
},
|
||||||
hir::TraitBoundModifier::None,
|
hir::TraitBoundModifier::None,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -471,10 +473,10 @@ where
|
||||||
let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
|
let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
|
||||||
let mut ty_to_traits: FxHashMap<Type, FxHashSet<Path>> = Default::default();
|
let mut ty_to_traits: FxHashMap<Type, FxHashSet<Path>> = Default::default();
|
||||||
|
|
||||||
let mut ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)> = Default::default();
|
let mut ty_to_fn: FxHashMap<Type, (PolyTrait, Option<Type>)> = Default::default();
|
||||||
|
|
||||||
for p in clean_where_predicates {
|
for p in clean_where_predicates {
|
||||||
let (orig_p, p) = (p, p.clean(self.cx));
|
let (orig_p, p) = (p, clean_predicate(p, self.cx));
|
||||||
if p.is_none() {
|
if p.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -535,8 +537,8 @@ where
|
||||||
if is_fn {
|
if is_fn {
|
||||||
ty_to_fn
|
ty_to_fn
|
||||||
.entry(ty.clone())
|
.entry(ty.clone())
|
||||||
.and_modify(|e| *e = (Some(poly_trait.clone()), e.1.clone()))
|
.and_modify(|e| *e = (poly_trait.clone(), e.1.clone()))
|
||||||
.or_insert(((Some(poly_trait.clone())), None));
|
.or_insert(((poly_trait.clone()), None));
|
||||||
|
|
||||||
ty_to_bounds.entry(ty.clone()).or_default();
|
ty_to_bounds.entry(ty.clone()).or_default();
|
||||||
} else {
|
} else {
|
||||||
|
@ -559,7 +561,13 @@ where
|
||||||
.and_modify(|e| {
|
.and_modify(|e| {
|
||||||
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
|
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
|
||||||
})
|
})
|
||||||
.or_insert((None, Some(rhs.ty().unwrap().clone())));
|
.or_insert((
|
||||||
|
PolyTrait {
|
||||||
|
trait_: trait_.clone(),
|
||||||
|
generic_params: Vec::new(),
|
||||||
|
},
|
||||||
|
Some(rhs.ty().unwrap().clone()),
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,7 @@ pub(crate) fn try_inline_glob(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
res: Res,
|
res: Res,
|
||||||
visited: &mut FxHashSet<DefId>,
|
visited: &mut FxHashSet<DefId>,
|
||||||
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
) -> Option<Vec<clean::Item>> {
|
) -> Option<Vec<clean::Item>> {
|
||||||
let did = res.opt_def_id()?;
|
let did = res.opt_def_id()?;
|
||||||
if did.is_local() {
|
if did.is_local() {
|
||||||
|
@ -153,8 +154,17 @@ pub(crate) fn try_inline_glob(
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Res::Def(DefKind::Mod, did) => {
|
Res::Def(DefKind::Mod, did) => {
|
||||||
let m = build_module(cx, did, visited);
|
let mut items = build_module_items(cx, did, visited, inlined_names);
|
||||||
Some(m.items)
|
items.drain_filter(|item| {
|
||||||
|
if let Some(name) = item.name {
|
||||||
|
// If an item with the same type and name already exists,
|
||||||
|
// it takes priority over the inlined stuff.
|
||||||
|
!inlined_names.insert((item.type_(), name))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Some(items)
|
||||||
}
|
}
|
||||||
// glob imports on things like enums aren't inlined even for local exports, so just bail
|
// glob imports on things like enums aren't inlined even for local exports, so just bail
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -517,6 +527,18 @@ fn build_module(
|
||||||
did: DefId,
|
did: DefId,
|
||||||
visited: &mut FxHashSet<DefId>,
|
visited: &mut FxHashSet<DefId>,
|
||||||
) -> clean::Module {
|
) -> clean::Module {
|
||||||
|
let items = build_module_items(cx, did, visited, &mut FxHashSet::default());
|
||||||
|
|
||||||
|
let span = clean::Span::new(cx.tcx.def_span(did));
|
||||||
|
clean::Module { items, span }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_module_items(
|
||||||
|
cx: &mut DocContext<'_>,
|
||||||
|
did: DefId,
|
||||||
|
visited: &mut FxHashSet<DefId>,
|
||||||
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
|
) -> Vec<clean::Item> {
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
// If we're re-exporting a re-export it may actually re-export something in
|
// If we're re-exporting a re-export it may actually re-export something in
|
||||||
|
@ -526,7 +548,13 @@ fn build_module(
|
||||||
if item.vis.is_public() {
|
if item.vis.is_public() {
|
||||||
let res = item.res.expect_non_local();
|
let res = item.res.expect_non_local();
|
||||||
if let Some(def_id) = res.mod_def_id() {
|
if let Some(def_id) = res.mod_def_id() {
|
||||||
if did == def_id || !visited.insert(def_id) {
|
// If we're inlining a glob import, it's possible to have
|
||||||
|
// two distinct modules with the same name. We don't want to
|
||||||
|
// inline it, or mark any of its contents as visited.
|
||||||
|
if did == def_id
|
||||||
|
|| inlined_names.contains(&(ItemType::Module, item.ident.name))
|
||||||
|
|| !visited.insert(def_id)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,8 +591,7 @@ fn build_module(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = clean::Span::new(cx.tcx.def_span(did));
|
items
|
||||||
clean::Module { items, span }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
|
pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
|
||||||
// priority to the not-imported one, so we should, too.
|
// priority to the not-imported one, so we should, too.
|
||||||
items.extend(self.items.iter().flat_map(|(item, renamed)| {
|
items.extend(self.items.iter().flat_map(|(item, renamed)| {
|
||||||
// First, lower everything other than imports.
|
// First, lower everything other than imports.
|
||||||
if matches!(item.kind, hir::ItemKind::Use(..)) {
|
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
let v = clean_maybe_renamed_item(cx, item, *renamed);
|
let v = clean_maybe_renamed_item(cx, item, *renamed);
|
||||||
|
@ -84,20 +84,13 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
|
||||||
}));
|
}));
|
||||||
items.extend(self.items.iter().flat_map(|(item, renamed)| {
|
items.extend(self.items.iter().flat_map(|(item, renamed)| {
|
||||||
// Now we actually lower the imports, skipping everything else.
|
// Now we actually lower the imports, skipping everything else.
|
||||||
if !matches!(item.kind, hir::ItemKind::Use(..)) {
|
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
|
||||||
return Vec::new();
|
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
|
||||||
|
clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
|
||||||
|
} else {
|
||||||
|
// skip everything else
|
||||||
|
Vec::new()
|
||||||
}
|
}
|
||||||
let mut v = clean_maybe_renamed_item(cx, item, *renamed);
|
|
||||||
v.drain_filter(|item| {
|
|
||||||
if let Some(name) = item.name {
|
|
||||||
// If an item with the same type and name already exists,
|
|
||||||
// it takes priority over the inlined stuff.
|
|
||||||
!inserted.insert((item.type_(), name))
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
v
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// determine if we should display the inner contents or
|
// determine if we should display the inner contents or
|
||||||
|
@ -266,66 +259,68 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
|
fn clean_where_predicate<'tcx>(
|
||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
|
predicate: &hir::WherePredicate<'tcx>,
|
||||||
if !self.in_where_clause() {
|
cx: &mut DocContext<'tcx>,
|
||||||
return None;
|
) -> Option<WherePredicate> {
|
||||||
}
|
if !predicate.in_where_clause() {
|
||||||
Some(match *self {
|
return None;
|
||||||
hir::WherePredicate::BoundPredicate(ref wbp) => {
|
|
||||||
let bound_params = wbp
|
|
||||||
.bound_generic_params
|
|
||||||
.iter()
|
|
||||||
.map(|param| {
|
|
||||||
// Higher-ranked params must be lifetimes.
|
|
||||||
// Higher-ranked lifetimes can't have bounds.
|
|
||||||
assert_matches!(
|
|
||||||
param,
|
|
||||||
hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
|
|
||||||
);
|
|
||||||
Lifetime(param.name.ident().name)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
WherePredicate::BoundPredicate {
|
|
||||||
ty: clean_ty(wbp.bounded_ty, cx),
|
|
||||||
bounds: wbp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
|
||||||
bound_params,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
|
||||||
lifetime: clean_lifetime(wrp.lifetime, cx),
|
|
||||||
bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
|
||||||
},
|
|
||||||
|
|
||||||
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
|
||||||
lhs: clean_ty(wrp.lhs_ty, cx),
|
|
||||||
rhs: clean_ty(wrp.rhs_ty, cx).into(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
Some(match *predicate {
|
||||||
|
hir::WherePredicate::BoundPredicate(ref wbp) => {
|
||||||
|
let bound_params = wbp
|
||||||
|
.bound_generic_params
|
||||||
|
.iter()
|
||||||
|
.map(|param| {
|
||||||
|
// Higher-ranked params must be lifetimes.
|
||||||
|
// Higher-ranked lifetimes can't have bounds.
|
||||||
|
assert_matches!(
|
||||||
|
param,
|
||||||
|
hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
|
||||||
|
);
|
||||||
|
Lifetime(param.name.ident().name)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
WherePredicate::BoundPredicate {
|
||||||
|
ty: clean_ty(wbp.bounded_ty, cx),
|
||||||
|
bounds: wbp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
|
bound_params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
||||||
|
lifetime: clean_lifetime(wrp.lifetime, cx),
|
||||||
|
bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
|
},
|
||||||
|
|
||||||
|
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
||||||
|
lhs: clean_ty(wrp.lhs_ty, cx),
|
||||||
|
rhs: clean_ty(wrp.rhs_ty, cx).into(),
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<'tcx, Option<WherePredicate>> for ty::Predicate<'tcx> {
|
pub(crate) fn clean_predicate<'tcx>(
|
||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
|
predicate: ty::Predicate<'tcx>,
|
||||||
let bound_predicate = self.kind();
|
cx: &mut DocContext<'tcx>,
|
||||||
match bound_predicate.skip_binder() {
|
) -> Option<WherePredicate> {
|
||||||
ty::PredicateKind::Trait(pred) => {
|
let bound_predicate = predicate.kind();
|
||||||
clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
|
match bound_predicate.skip_binder() {
|
||||||
}
|
ty::PredicateKind::Trait(pred) => {
|
||||||
ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
|
clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
|
||||||
ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
|
|
||||||
ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
|
|
||||||
ty::PredicateKind::ConstEvaluatable(..) => None,
|
|
||||||
ty::PredicateKind::WellFormed(..) => None,
|
|
||||||
|
|
||||||
ty::PredicateKind::Subtype(..)
|
|
||||||
| ty::PredicateKind::Coerce(..)
|
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
|
||||||
| ty::PredicateKind::ClosureKind(..)
|
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
|
||||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
|
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
|
||||||
|
ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
|
||||||
|
ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
|
||||||
|
ty::PredicateKind::ConstEvaluatable(..) => None,
|
||||||
|
ty::PredicateKind::WellFormed(..) => None,
|
||||||
|
|
||||||
|
ty::PredicateKind::Subtype(..)
|
||||||
|
| ty::PredicateKind::Coerce(..)
|
||||||
|
| ty::PredicateKind::ObjectSafe(..)
|
||||||
|
| ty::PredicateKind::ClosureKind(..)
|
||||||
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
|
| ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +596,11 @@ impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
|
||||||
|
|
||||||
let mut generics = Generics {
|
let mut generics = Generics {
|
||||||
params,
|
params,
|
||||||
where_predicates: self.predicates.iter().filter_map(|x| x.clean(cx)).collect(),
|
where_predicates: self
|
||||||
|
.predicates
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| clean_where_predicate(x, cx))
|
||||||
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some duplicates are generated for ?Sized bounds between type params and where
|
// Some duplicates are generated for ?Sized bounds between type params and where
|
||||||
|
@ -702,7 +701,7 @@ fn clean_ty_generics<'tcx>(
|
||||||
|
|
||||||
if let Some(param_idx) = param_idx {
|
if let Some(param_idx) = param_idx {
|
||||||
if let Some(b) = impl_trait.get_mut(¶m_idx.into()) {
|
if let Some(b) = impl_trait.get_mut(¶m_idx.into()) {
|
||||||
let p: WherePredicate = p.clean(cx)?;
|
let p: WherePredicate = clean_predicate(*p, cx)?;
|
||||||
|
|
||||||
b.extend(
|
b.extend(
|
||||||
p.get_bounds()
|
p.get_bounds()
|
||||||
|
@ -759,7 +758,7 @@ fn clean_ty_generics<'tcx>(
|
||||||
// Now that `cx.impl_trait_bounds` is populated, we can process
|
// Now that `cx.impl_trait_bounds` is populated, we can process
|
||||||
// remaining predicates which could contain `impl Trait`.
|
// remaining predicates which could contain `impl Trait`.
|
||||||
let mut where_predicates =
|
let mut where_predicates =
|
||||||
where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
|
where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
|
||||||
|
|
||||||
// Type parameters have a Sized bound by default unless removed with
|
// Type parameters have a Sized bound by default unless removed with
|
||||||
// ?Sized. Scan through the predicates and mark any type parameter with
|
// ?Sized. Scan through the predicates and mark any type parameter with
|
||||||
|
@ -1962,7 +1961,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
||||||
return clean_extern_crate(item, name, orig_name, cx);
|
return clean_extern_crate(item, name, orig_name, cx);
|
||||||
}
|
}
|
||||||
ItemKind::Use(path, kind) => {
|
ItemKind::Use(path, kind) => {
|
||||||
return clean_use_statement(item, name, path, kind, cx);
|
return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default());
|
||||||
}
|
}
|
||||||
_ => unreachable!("not yet converted"),
|
_ => unreachable!("not yet converted"),
|
||||||
};
|
};
|
||||||
|
@ -2083,6 +2082,7 @@ fn clean_use_statement<'tcx>(
|
||||||
path: &hir::Path<'tcx>,
|
path: &hir::Path<'tcx>,
|
||||||
kind: hir::UseKind,
|
kind: hir::UseKind,
|
||||||
cx: &mut DocContext<'tcx>,
|
cx: &mut DocContext<'tcx>,
|
||||||
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
) -> Vec<Item> {
|
) -> Vec<Item> {
|
||||||
// We need this comparison because some imports (for std types for example)
|
// We need this comparison because some imports (for std types for example)
|
||||||
// are "inserted" as well but directly by the compiler and they should not be
|
// are "inserted" as well but directly by the compiler and they should not be
|
||||||
|
@ -2148,7 +2148,8 @@ fn clean_use_statement<'tcx>(
|
||||||
let inner = if kind == hir::UseKind::Glob {
|
let inner = if kind == hir::UseKind::Glob {
|
||||||
if !denied {
|
if !denied {
|
||||||
let mut visited = FxHashSet::default();
|
let mut visited = FxHashSet::default();
|
||||||
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
|
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited, inlined_names)
|
||||||
|
{
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1550,6 +1550,15 @@ fn render_impl(
|
||||||
rendering_params: ImplRenderingParameters,
|
rendering_params: ImplRenderingParameters,
|
||||||
) {
|
) {
|
||||||
for trait_item in &t.items {
|
for trait_item in &t.items {
|
||||||
|
// Skip over any default trait items that are impossible to call
|
||||||
|
// (e.g. if it has a `Self: Sized` bound on an unsized type).
|
||||||
|
if let Some(impl_def_id) = parent.item_id.as_def_id()
|
||||||
|
&& let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
|
||||||
|
&& cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let n = trait_item.name;
|
let n = trait_item.name;
|
||||||
if i.items.iter().any(|m| m.name == n) {
|
if i.items.iter().any(|m| m.name == n) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -119,6 +119,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I, T, U> FromWithTcx<I> for Vec<U>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = T>,
|
||||||
|
U: FromWithTcx<T>,
|
||||||
|
{
|
||||||
|
fn from_tcx(f: I, tcx: TyCtxt<'_>) -> Vec<U> {
|
||||||
|
f.into_iter().map(|x| x.into_tcx(tcx)).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
|
pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
|
let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
|
||||||
|
@ -130,11 +140,11 @@ impl FromWithTcx<clean::GenericArgs> for GenericArgs {
|
||||||
use clean::GenericArgs::*;
|
use clean::GenericArgs::*;
|
||||||
match args {
|
match args {
|
||||||
AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
|
AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
|
||||||
args: args.into_vec().into_iter().map(|a| a.into_tcx(tcx)).collect(),
|
args: args.into_vec().into_tcx(tcx),
|
||||||
bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(),
|
bindings: bindings.into_tcx(tcx),
|
||||||
},
|
},
|
||||||
Parenthesized { inputs, output } => GenericArgs::Parenthesized {
|
Parenthesized { inputs, output } => GenericArgs::Parenthesized {
|
||||||
inputs: inputs.into_vec().into_iter().map(|a| a.into_tcx(tcx)).collect(),
|
inputs: inputs.into_vec().into_tcx(tcx),
|
||||||
output: output.map(|a| (*a).into_tcx(tcx)),
|
output: output.map(|a| (*a).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -145,7 +155,7 @@ impl FromWithTcx<clean::GenericArg> for GenericArg {
|
||||||
fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
|
||||||
use clean::GenericArg::*;
|
use clean::GenericArg::*;
|
||||||
match arg {
|
match arg {
|
||||||
Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
|
Lifetime(l) => GenericArg::Lifetime(convert_lifetime(l)),
|
||||||
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
|
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
|
||||||
Const(box c) => GenericArg::Const(c.into_tcx(tcx)),
|
Const(box c) => GenericArg::Const(c.into_tcx(tcx)),
|
||||||
Infer => GenericArg::Infer,
|
Infer => GenericArg::Infer,
|
||||||
|
@ -177,9 +187,7 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
|
||||||
use clean::TypeBindingKind::*;
|
use clean::TypeBindingKind::*;
|
||||||
match kind {
|
match kind {
|
||||||
Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
|
Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
|
||||||
Constraint { bounds } => {
|
Constraint { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)),
|
||||||
TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +252,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
|
||||||
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
|
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
|
||||||
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
|
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
|
||||||
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
|
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
|
||||||
ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
|
ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)),
|
||||||
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
|
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
|
||||||
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
|
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
|
||||||
ForeignTypeItem => ItemEnum::ForeignType,
|
ForeignTypeItem => ItemEnum::ForeignType,
|
||||||
|
@ -260,12 +268,12 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
|
||||||
}
|
}
|
||||||
TyAssocTypeItem(g, b) => ItemEnum::AssocType {
|
TyAssocTypeItem(g, b) => ItemEnum::AssocType {
|
||||||
generics: (*g).into_tcx(tcx),
|
generics: (*g).into_tcx(tcx),
|
||||||
bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: b.into_tcx(tcx),
|
||||||
default: None,
|
default: None,
|
||||||
},
|
},
|
||||||
AssocTypeItem(t, b) => ItemEnum::AssocType {
|
AssocTypeItem(t, b) => ItemEnum::AssocType {
|
||||||
generics: t.generics.into_tcx(tcx),
|
generics: t.generics.into_tcx(tcx),
|
||||||
bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: b.into_tcx(tcx),
|
||||||
default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
|
default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
// `convert_item` early returns `None` for stripped items and keywords.
|
// `convert_item` early returns `None` for stripped items and keywords.
|
||||||
|
@ -347,15 +355,15 @@ fn convert_abi(a: RustcAbi) -> Abi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_lifetime(l: clean::Lifetime) -> String {
|
||||||
|
l.0.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
impl FromWithTcx<clean::Generics> for Generics {
|
impl FromWithTcx<clean::Generics> for Generics {
|
||||||
fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
|
||||||
Generics {
|
Generics {
|
||||||
params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
params: generics.params.into_tcx(tcx),
|
||||||
where_predicates: generics
|
where_predicates: generics.where_predicates.into_tcx(tcx),
|
||||||
.where_predicates
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.into_tcx(tcx))
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,10 +382,10 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
|
||||||
use clean::GenericParamDefKind::*;
|
use clean::GenericParamDefKind::*;
|
||||||
match kind {
|
match kind {
|
||||||
Lifetime { outlives } => GenericParamDefKind::Lifetime {
|
Lifetime { outlives } => GenericParamDefKind::Lifetime {
|
||||||
outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
|
outlives: outlives.into_iter().map(convert_lifetime).collect(),
|
||||||
},
|
},
|
||||||
Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type {
|
Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type {
|
||||||
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: bounds.into_tcx(tcx),
|
||||||
default: default.map(|x| (*x).into_tcx(tcx)),
|
default: default.map(|x| (*x).into_tcx(tcx)),
|
||||||
synthetic,
|
synthetic,
|
||||||
},
|
},
|
||||||
|
@ -395,7 +403,7 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
||||||
match predicate {
|
match predicate {
|
||||||
BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
|
BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
|
||||||
type_: ty.into_tcx(tcx),
|
type_: ty.into_tcx(tcx),
|
||||||
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: bounds.into_tcx(tcx),
|
||||||
generic_params: bound_params
|
generic_params: bound_params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| GenericParamDef {
|
.map(|x| GenericParamDef {
|
||||||
|
@ -405,8 +413,8 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
|
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
|
||||||
lifetime: lifetime.0.to_string(),
|
lifetime: convert_lifetime(lifetime),
|
||||||
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: bounds.into_tcx(tcx),
|
||||||
},
|
},
|
||||||
EqPredicate { lhs, rhs } => {
|
EqPredicate { lhs, rhs } => {
|
||||||
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
|
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
|
||||||
|
@ -424,11 +432,11 @@ impl FromWithTcx<clean::GenericBound> for GenericBound {
|
||||||
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
|
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
|
||||||
GenericBound::TraitBound {
|
GenericBound::TraitBound {
|
||||||
trait_,
|
trait_,
|
||||||
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
generic_params: generic_params.into_tcx(tcx),
|
||||||
modifier: from_trait_bound_modifier(modifier),
|
modifier: from_trait_bound_modifier(modifier),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()),
|
Outlives(lifetime) => GenericBound::Outlives(convert_lifetime(lifetime)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,8 +455,8 @@ pub(crate) fn from_trait_bound_modifier(
|
||||||
impl FromWithTcx<clean::Type> for Type {
|
impl FromWithTcx<clean::Type> for Type {
|
||||||
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
||||||
use clean::Type::{
|
use clean::Type::{
|
||||||
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive,
|
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||||
QPath, RawPointer, Slice, Tuple,
|
RawPointer, Slice, Tuple,
|
||||||
};
|
};
|
||||||
|
|
||||||
match ty {
|
match ty {
|
||||||
|
@ -458,40 +466,24 @@ impl FromWithTcx<clean::Type> for Type {
|
||||||
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
|
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
|
||||||
param_names: Vec::new(),
|
param_names: Vec::new(),
|
||||||
},
|
},
|
||||||
DynTrait(mut bounds, lt) => {
|
clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
|
||||||
let first_trait = bounds.remove(0).trait_;
|
lifetime: lt.map(convert_lifetime),
|
||||||
|
traits: bounds.into_tcx(tcx),
|
||||||
Type::ResolvedPath {
|
}),
|
||||||
name: first_trait.whole_name(),
|
|
||||||
id: from_item_id(first_trait.def_id().into(), tcx),
|
|
||||||
args: first_trait
|
|
||||||
.segments
|
|
||||||
.last()
|
|
||||||
.map(|args| Box::new(args.clone().args.into_tcx(tcx))),
|
|
||||||
param_names: bounds
|
|
||||||
.into_iter()
|
|
||||||
.map(|t| {
|
|
||||||
clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
|
|
||||||
})
|
|
||||||
.chain(lt.map(clean::GenericBound::Outlives))
|
|
||||||
.map(|bound| bound.into_tcx(tcx))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generic(s) => Type::Generic(s.to_string()),
|
Generic(s) => Type::Generic(s.to_string()),
|
||||||
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
|
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
|
||||||
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
||||||
Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
|
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
||||||
Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
|
Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
|
||||||
Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
|
Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
|
||||||
ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()),
|
ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
|
||||||
Infer => Type::Infer,
|
Infer => Type::Infer,
|
||||||
RawPointer(mutability, type_) => Type::RawPointer {
|
RawPointer(mutability, type_) => Type::RawPointer {
|
||||||
mutable: mutability == ast::Mutability::Mut,
|
mutable: mutability == ast::Mutability::Mut,
|
||||||
type_: Box::new((*type_).into_tcx(tcx)),
|
type_: Box::new((*type_).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
|
BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
|
||||||
lifetime: lifetime.map(|l| l.0.to_string()),
|
lifetime: lifetime.map(convert_lifetime),
|
||||||
mutable: mutability == ast::Mutability::Mut,
|
mutable: mutability == ast::Mutability::Mut,
|
||||||
type_: Box::new((*type_).into_tcx(tcx)),
|
type_: Box::new((*type_).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
|
@ -528,7 +520,7 @@ impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
|
||||||
async_: false,
|
async_: false,
|
||||||
abi: convert_abi(abi),
|
abi: convert_abi(abi),
|
||||||
},
|
},
|
||||||
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
generic_params: generic_params.into_tcx(tcx),
|
||||||
decl: decl.into_tcx(tcx),
|
decl: decl.into_tcx(tcx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,16 +554,28 @@ impl FromWithTcx<clean::Trait> for Trait {
|
||||||
is_unsafe,
|
is_unsafe,
|
||||||
items: ids(items, tcx),
|
items: ids(items, tcx),
|
||||||
generics: generics.into_tcx(tcx),
|
generics: generics.into_tcx(tcx),
|
||||||
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: bounds.into_tcx(tcx),
|
||||||
implementations: Vec::new(), // Added in JsonRenderer::item
|
implementations: Vec::new(), // Added in JsonRenderer::item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWithTcx<Box<clean::Impl>> for Impl {
|
impl FromWithTcx<clean::PolyTrait> for PolyTrait {
|
||||||
fn from_tcx(impl_: Box<clean::Impl>, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(
|
||||||
|
clean::PolyTrait { trait_, generic_params }: clean::PolyTrait,
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
) -> Self {
|
||||||
|
PolyTrait {
|
||||||
|
trait_: clean::Type::Path { path: trait_ }.into_tcx(tcx),
|
||||||
|
generic_params: generic_params.into_tcx(tcx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWithTcx<clean::Impl> for Impl {
|
||||||
|
fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
|
||||||
let provided_trait_methods = impl_.provided_trait_methods(tcx);
|
let provided_trait_methods = impl_.provided_trait_methods(tcx);
|
||||||
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = *impl_;
|
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
|
||||||
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
|
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
|
||||||
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
||||||
// FIXME: use something like ImplKind in JSON?
|
// FIXME: use something like ImplKind in JSON?
|
||||||
|
@ -730,10 +734,7 @@ impl FromWithTcx<Box<clean::Typedef>> for Typedef {
|
||||||
|
|
||||||
impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
|
impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
|
||||||
fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
|
||||||
OpaqueTy {
|
OpaqueTy { bounds: opaque.bounds.into_tcx(tcx), generics: opaque.generics.into_tcx(tcx) }
|
||||||
bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
|
||||||
generics: opaque.generics.into_tcx(tcx),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,10 +750,7 @@ impl FromWithTcx<clean::Static> for Static {
|
||||||
|
|
||||||
impl FromWithTcx<clean::TraitAlias> for TraitAlias {
|
impl FromWithTcx<clean::TraitAlias> for TraitAlias {
|
||||||
fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
|
||||||
TraitAlias {
|
TraitAlias { generics: alias.generics.into_tcx(tcx), params: alias.bounds.into_tcx(tcx) }
|
||||||
generics: alias.generics.into_tcx(tcx),
|
|
||||||
params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::path::PathBuf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// rustdoc format-version.
|
/// rustdoc format-version.
|
||||||
pub const FORMAT_VERSION: u32 = 16;
|
pub const FORMAT_VERSION: u32 = 17;
|
||||||
|
|
||||||
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
||||||
/// about the language items in the local crate, as well as info about external items to allow
|
/// about the language items in the local crate, as well as info about external items to allow
|
||||||
|
@ -115,6 +115,35 @@ pub enum Visibility {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub struct DynTrait {
|
||||||
|
/// All the traits implemented. One of them is the vtable, and the rest must be auto traits.
|
||||||
|
pub traits: Vec<PolyTrait>,
|
||||||
|
/// The lifetime of the whole dyn object
|
||||||
|
/// ```text
|
||||||
|
/// dyn Debug + 'static
|
||||||
|
/// ^^^^^^^
|
||||||
|
/// |
|
||||||
|
/// this part
|
||||||
|
/// ```
|
||||||
|
pub lifetime: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
/// A trait and potential HRTBs
|
||||||
|
pub struct PolyTrait {
|
||||||
|
#[serde(rename = "trait")]
|
||||||
|
pub trait_: Type,
|
||||||
|
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
||||||
|
/// ```text
|
||||||
|
/// dyn for<'a> Fn() -> &'a i32"
|
||||||
|
/// ^^^^^^^
|
||||||
|
/// |
|
||||||
|
/// this part
|
||||||
|
/// ```
|
||||||
|
pub generic_params: Vec<GenericParamDef>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum GenericArgs {
|
pub enum GenericArgs {
|
||||||
|
@ -395,7 +424,7 @@ pub enum WherePredicate {
|
||||||
type_: Type,
|
type_: Type,
|
||||||
bounds: Vec<GenericBound>,
|
bounds: Vec<GenericBound>,
|
||||||
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
||||||
/// ```plain
|
/// ```text
|
||||||
/// where for<'a> &'a T: Iterator,"
|
/// where for<'a> &'a T: Iterator,"
|
||||||
/// ^^^^^^^
|
/// ^^^^^^^
|
||||||
/// |
|
/// |
|
||||||
|
@ -420,7 +449,7 @@ pub enum GenericBound {
|
||||||
#[serde(rename = "trait")]
|
#[serde(rename = "trait")]
|
||||||
trait_: Type,
|
trait_: Type,
|
||||||
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
||||||
/// ```plain
|
/// ```text
|
||||||
/// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
|
/// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
|
||||||
/// ^^^^^^^^^^^
|
/// ^^^^^^^^^^^
|
||||||
/// |
|
/// |
|
||||||
|
@ -458,6 +487,7 @@ pub enum Type {
|
||||||
args: Option<Box<GenericArgs>>,
|
args: Option<Box<GenericArgs>>,
|
||||||
param_names: Vec<GenericBound>,
|
param_names: Vec<GenericBound>,
|
||||||
},
|
},
|
||||||
|
DynTrait(DynTrait),
|
||||||
/// Parameterized types
|
/// Parameterized types
|
||||||
Generic(String),
|
Generic(String),
|
||||||
/// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
|
/// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
|
||||||
|
@ -505,7 +535,7 @@ pub enum Type {
|
||||||
pub struct FunctionPointer {
|
pub struct FunctionPointer {
|
||||||
pub decl: FnDecl,
|
pub decl: FnDecl,
|
||||||
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
/// Used for Higher-Rank Trait Bounds (HRTBs)
|
||||||
/// ```plain
|
/// ```text
|
||||||
/// for<'c> fn(val: &'c i32) -> i32
|
/// for<'c> fn(val: &'c i32) -> i32
|
||||||
/// ^^^^^^^
|
/// ^^^^^^^
|
||||||
/// |
|
/// |
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items" 1
|
// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items[*]" 3
|
||||||
// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
|
// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
|
||||||
// @is - "$.index[*][?(@.name=='dyn')].inner.items[0]" $sync_int_gen
|
// @set ref_fn = - "$.index[*][?(@.name=='RefFn')].id"
|
||||||
|
// @set weird_order = - "$.index[*][?(@.name=='WeirdOrder')].id"
|
||||||
|
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen
|
||||||
|
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $ref_fn
|
||||||
|
// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $weird_order
|
||||||
|
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
|
||||||
|
@ -10,12 +15,35 @@
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
|
||||||
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
|
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\"
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\"
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\"
|
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3
|
||||||
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" []
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" []
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" []
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}"
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Fn"'
|
||||||
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Send"'
|
||||||
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.inner.name" '"Sync"'
|
||||||
|
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
|
||||||
pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
|
pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].kind" \"typedef\"
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\""
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null
|
||||||
|
// @count - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.kind" '"resolved_path"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.name" '"Fn"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.kind" '"borrowed_ref"'
|
||||||
|
// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.inner.lifetime" "\"'b\""
|
||||||
|
pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
|
||||||
|
|
||||||
|
// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Send"'
|
||||||
|
// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Debug"'
|
||||||
|
pub type WeirdOrder = Box<dyn Send + Debug>;
|
||||||
|
|
26
src/test/rustdoc-json/type/hrtb.rs
Normal file
26
src/test/rustdoc-json/type/hrtb.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
// @has hrtb.json
|
||||||
|
|
||||||
|
// @is - "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F","kind": "generic"}'
|
||||||
|
// @is - "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
|
||||||
|
pub fn genfn<F>(f: F)
|
||||||
|
where
|
||||||
|
for<'a, 'b> F: Fn(&'a i32, &'b i32),
|
||||||
|
{
|
||||||
|
let zero = 0;
|
||||||
|
f(&zero, &zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"'
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null
|
||||||
|
// @count - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
|
||||||
|
// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.inner.name" '"Fn"'
|
||||||
|
pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
|
||||||
|
let zero = 0;
|
||||||
|
f(&zero, &zero);
|
||||||
|
}
|
13
src/test/rustdoc/auxiliary/issue-100204-aux.rs
Normal file
13
src/test/rustdoc/auxiliary/issue-100204-aux.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![crate_name="first"]
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::Bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bot;
|
||||||
|
|
||||||
|
impl Bot {
|
||||||
|
pub fn new() -> Bot {
|
||||||
|
Bot
|
||||||
|
}
|
||||||
|
}
|
21
src/test/rustdoc/fn-bound.rs
Normal file
21
src/test/rustdoc/fn-bound.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Regression test for #100143
|
||||||
|
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
|
pub struct Span<F: Fn(&i32)> {
|
||||||
|
inner: Peekable<ConditionalIterator<F>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConditionalIterator<F> {
|
||||||
|
f: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header in-band"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>'
|
||||||
|
impl<F: Fn(&i32)> Iterator for ConditionalIterator<F> {
|
||||||
|
type Item = ();
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
20
src/test/rustdoc/impossible-default.rs
Normal file
20
src/test/rustdoc/impossible-default.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
// Check that default trait items that are impossible to satisfy
|
||||||
|
|
||||||
|
pub trait Foo {
|
||||||
|
fn needs_sized(&self)
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{}
|
||||||
|
|
||||||
|
fn no_needs_sized(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @!has foo/struct.Bar.html '//*[@id="method.needs_sized"]//h4[@class="code-header"]' \
|
||||||
|
// "fn needs_sized"
|
||||||
|
// @has foo/struct.Bar.html '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' \
|
||||||
|
// "fn no_needs_sized"
|
||||||
|
pub struct Bar([u8]);
|
||||||
|
|
||||||
|
impl Foo for Bar {}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// aux-build:issue-100204-aux.rs
|
||||||
|
// build-aux-docs
|
||||||
|
// ignore-cross-compile
|
||||||
|
|
||||||
|
#![crate_name="second"]
|
||||||
|
|
||||||
|
extern crate first;
|
||||||
|
|
||||||
|
pub mod prelude {}
|
||||||
|
|
||||||
|
// @has first/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
|
||||||
|
// @has second/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use first::*;
|
|
@ -57,13 +57,11 @@ LL | a + 1
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:33:1
|
--> $DIR/naked-functions.rs:33:1
|
||||||
|
|
|
|
||||||
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
|
LL | pub unsafe extern "C" fn inc(a: u32) -> u32 {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | a + 1
|
LL |
|
||||||
| | ----- non-asm is unsupported in naked functions
|
LL | a + 1
|
||||||
LL | |
|
| ----- non-asm is unsupported in naked functions
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
||||||
error: referencing function parameters is not allowed in naked functions
|
error: referencing function parameters is not allowed in naked functions
|
||||||
--> $DIR/naked-functions.rs:42:31
|
--> $DIR/naked-functions.rs:42:31
|
||||||
|
@ -82,12 +80,11 @@ LL | asm!("/* {0} */", in(reg) a, options(noreturn));
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:48:1
|
--> $DIR/naked-functions.rs:48:1
|
||||||
|
|
|
|
||||||
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
|
LL | pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | (|| a + 1)()
|
LL |
|
||||||
| | ------------ non-asm is unsupported in naked functions
|
LL | (|| a + 1)()
|
||||||
LL | | }
|
| ------------ non-asm is unsupported in naked functions
|
||||||
| |_^
|
|
||||||
|
|
||||||
error[E0787]: only `const` and `sym` operands are supported in naked functions
|
error[E0787]: only `const` and `sym` operands are supported in naked functions
|
||||||
--> $DIR/naked-functions.rs:65:10
|
--> $DIR/naked-functions.rs:65:10
|
||||||
|
@ -124,30 +121,25 @@ LL | sym G, options(noreturn),
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:54:1
|
--> $DIR/naked-functions.rs:54:1
|
||||||
|
|
|
|
||||||
LL | / pub unsafe extern "C" fn unsupported_operands() {
|
LL | pub unsafe extern "C" fn unsupported_operands() {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | let mut a = 0usize;
|
LL |
|
||||||
| | ------------------- non-asm is unsupported in naked functions
|
LL | let mut a = 0usize;
|
||||||
LL | | let mut b = 0usize;
|
| ------------------- non-asm is unsupported in naked functions
|
||||||
| | ------------------- non-asm is unsupported in naked functions
|
LL | let mut b = 0usize;
|
||||||
LL | | let mut c = 0usize;
|
| ------------------- non-asm is unsupported in naked functions
|
||||||
| | ------------------- non-asm is unsupported in naked functions
|
LL | let mut c = 0usize;
|
||||||
LL | | let mut d = 0usize;
|
| ------------------- non-asm is unsupported in naked functions
|
||||||
| | ------------------- non-asm is unsupported in naked functions
|
LL | let mut d = 0usize;
|
||||||
LL | | let mut e = 0usize;
|
| ------------------- non-asm is unsupported in naked functions
|
||||||
| | ------------------- non-asm is unsupported in naked functions
|
LL | let mut e = 0usize;
|
||||||
... |
|
| ------------------- non-asm is unsupported in naked functions
|
||||||
LL | | );
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:77:1
|
--> $DIR/naked-functions.rs:77:1
|
||||||
|
|
|
|
||||||
LL | / pub extern "C" fn missing_assembly() {
|
LL | pub extern "C" fn missing_assembly() {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
||||||
error[E0787]: asm in naked functions must use `noreturn` option
|
error[E0787]: asm in naked functions must use `noreturn` option
|
||||||
--> $DIR/naked-functions.rs:84:5
|
--> $DIR/naked-functions.rs:84:5
|
||||||
|
@ -185,20 +177,17 @@ LL | asm!("", options(noreturn));
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:82:1
|
--> $DIR/naked-functions.rs:82:1
|
||||||
|
|
|
|
||||||
LL | / pub extern "C" fn too_many_asm_blocks() {
|
LL | pub extern "C" fn too_many_asm_blocks() {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | asm!("");
|
...
|
||||||
LL | |
|
LL | asm!("");
|
||||||
LL | | asm!("");
|
| -------- multiple asm blocks are unsupported in naked functions
|
||||||
| | -------- multiple asm blocks are unsupported in naked functions
|
LL |
|
||||||
LL | |
|
LL | asm!("");
|
||||||
LL | | asm!("");
|
| -------- multiple asm blocks are unsupported in naked functions
|
||||||
| | -------- multiple asm blocks are unsupported in naked functions
|
LL |
|
||||||
LL | |
|
LL | asm!("", options(noreturn));
|
||||||
LL | | asm!("", options(noreturn));
|
| --------------------------- multiple asm blocks are unsupported in naked functions
|
||||||
| | --------------------------- multiple asm blocks are unsupported in naked functions
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
||||||
error: referencing function parameters is not allowed in naked functions
|
error: referencing function parameters is not allowed in naked functions
|
||||||
--> $DIR/naked-functions.rs:97:11
|
--> $DIR/naked-functions.rs:97:11
|
||||||
|
@ -211,13 +200,11 @@ LL | *&y
|
||||||
error[E0787]: naked functions must contain a single asm block
|
error[E0787]: naked functions must contain a single asm block
|
||||||
--> $DIR/naked-functions.rs:95:5
|
--> $DIR/naked-functions.rs:95:5
|
||||||
|
|
|
|
||||||
LL | / pub extern "C" fn inner(y: usize) -> usize {
|
LL | pub extern "C" fn inner(y: usize) -> usize {
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | *&y
|
LL |
|
||||||
| | --- non-asm is unsupported in naked functions
|
LL | *&y
|
||||||
LL | |
|
| --- non-asm is unsupported in naked functions
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
||||||
error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
||||||
--> $DIR/naked-functions.rs:105:5
|
--> $DIR/naked-functions.rs:105:5
|
||||||
|
@ -249,18 +236,18 @@ LL | asm!("", options(noreturn, may_unwind));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: Rust ABI is unsupported in naked functions
|
warning: Rust ABI is unsupported in naked functions
|
||||||
--> $DIR/naked-functions.rs:124:15
|
--> $DIR/naked-functions.rs:124:1
|
||||||
|
|
|
|
||||||
LL | pub unsafe fn default_abi() {
|
LL | pub unsafe fn default_abi() {
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(undefined_naked_function_abi)]` on by default
|
= note: `#[warn(undefined_naked_function_abi)]` on by default
|
||||||
|
|
||||||
warning: Rust ABI is unsupported in naked functions
|
warning: Rust ABI is unsupported in naked functions
|
||||||
--> $DIR/naked-functions.rs:130:15
|
--> $DIR/naked-functions.rs:130:1
|
||||||
|
|
|
|
||||||
LL | pub unsafe fn rust_abi() {
|
LL | pub unsafe fn rust_abi() {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
error: naked functions cannot be inlined
|
||||||
--> $DIR/naked-functions.rs:170:1
|
--> $DIR/naked-functions.rs:170:1
|
||||||
|
|
|
@ -4,5 +4,5 @@ trait I32Iterator = Iterator<Item = i32>;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == i32`
|
error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||||
--> $DIR/associated-types-overridden-binding-2.rs:6:43
|
--> $DIR/associated-types-overridden-binding-2.rs:6:43
|
||||||
|
|
|
|
||||||
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn return_targets_async_block_not_fn() -> u8 {
|
||||||
return 0u8;
|
return 0u8;
|
||||||
};
|
};
|
||||||
let _: &dyn Future<Output = ()> = █
|
let _: &dyn Future<Output = ()> = █
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn return_targets_async_block_not_async_fn() -> u8 {
|
async fn return_targets_async_block_not_async_fn() -> u8 {
|
||||||
|
@ -24,7 +24,7 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
|
||||||
return 0u8;
|
return 0u8;
|
||||||
};
|
};
|
||||||
let _: &dyn Future<Output = ()> = █
|
let _: &dyn Future<Output = ()> = █
|
||||||
//~^ ERROR type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
|
//~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_break_in_async_block() {
|
fn no_break_in_async_block() {
|
||||||
|
@ -42,7 +42,9 @@ fn no_break_in_async_block_even_with_outer_loop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyErr;
|
struct MyErr;
|
||||||
fn err() -> Result<u8, MyErr> { Err(MyErr) }
|
fn err() -> Result<u8, MyErr> {
|
||||||
|
Err(MyErr)
|
||||||
|
}
|
||||||
|
|
||||||
fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
|
fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
|
|
@ -31,7 +31,7 @@ LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^ expected `u8`, found `()`
|
| |_^ expected `u8`, found `()`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
|
error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Future<Output = ()> = █
|
LL | let _: &dyn Future<Output = ()> = █
|
||||||
|
@ -47,7 +47,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
|
||||||
| |
|
| |
|
||||||
| implicitly returns `()` as its body has no tail or `return` expression
|
| implicitly returns `()` as its body has no tail or `return` expression
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
|
error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Future<Output = ()> = █
|
LL | let _: &dyn Future<Output = ()> = █
|
||||||
|
@ -56,7 +56,7 @@ LL | let _: &dyn Future<Output = ()> = █
|
||||||
= note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
|
= note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:47:44
|
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
||||||
|
|
|
|
||||||
LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
|
LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
|
||||||
| ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
|
| ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
|
||||||
|
@ -67,7 +67,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/async-block-control-flow-static-semantics.rs:56:50
|
--> $DIR/async-block-control-flow-static-semantics.rs:58:50
|
||||||
|
|
|
|
||||||
LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
|
LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
|
||||||
| ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
|
| ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
enum Eu64 {
|
enum Eu64 {
|
||||||
//~^ ERROR discriminant value `0` assigned more than once
|
//~^ ERROR discriminant value `0` assigned more than once
|
||||||
Au64 = 0,
|
Au64 = 0,
|
||||||
//~^NOTE first assignment of `0`
|
//~^NOTE `0` assigned here
|
||||||
Bu64 = 0x8000_0000_0000_0000
|
Bu64 = 0x8000_0000_0000_0000
|
||||||
//~^NOTE second assignment of `0` (overflowed from `9223372036854775808`)
|
//~^NOTE `0` (overflowed from `9223372036854775808`) assigned here
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -5,10 +5,10 @@ LL | enum Eu64 {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | Au64 = 0,
|
LL | Au64 = 0,
|
||||||
| - first assignment of `0`
|
| - `0` assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | Bu64 = 0x8000_0000_0000_0000
|
LL | Bu64 = 0x8000_0000_0000_0000
|
||||||
| --------------------- second assignment of `0` (overflowed from `9223372036854775808`)
|
| --------------------- `0` (overflowed from `9223372036854775808`) assigned here
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
enum Enum {
|
enum Enum {
|
||||||
//~^ ERROR discriminant value `3` assigned more than once
|
//~^ ERROR discriminant value `3` assigned more than once
|
||||||
P = 3,
|
P = 3,
|
||||||
//~^ NOTE first assignment of `3`
|
//~^ NOTE `3` assigned here
|
||||||
X = 3,
|
X = 3,
|
||||||
//~^ NOTE second assignment of `3`
|
//~^ NOTE `3` assigned here
|
||||||
Y = 5
|
Y = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,20 +11,43 @@ enum Enum {
|
||||||
enum EnumOverflowRepr {
|
enum EnumOverflowRepr {
|
||||||
//~^ ERROR discriminant value `1` assigned more than once
|
//~^ ERROR discriminant value `1` assigned more than once
|
||||||
P = 257,
|
P = 257,
|
||||||
//~^ NOTE first assignment of `1` (overflowed from `257`)
|
//~^ NOTE `1` (overflowed from `257`) assigned here
|
||||||
X = 513,
|
X = 513,
|
||||||
//~^ NOTE second assignment of `1` (overflowed from `513`)
|
//~^ NOTE `1` (overflowed from `513`) assigned here
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(i8)]
|
#[repr(i8)]
|
||||||
enum NegDisEnum {
|
enum NegDisEnum {
|
||||||
//~^ ERROR discriminant value `-1` assigned more than once
|
//~^ ERROR discriminant value `-1` assigned more than once
|
||||||
First = -1,
|
First = -1,
|
||||||
//~^ NOTE first assignment of `-1`
|
//~^ NOTE `-1` assigned here
|
||||||
Second = -2,
|
Second = -2,
|
||||||
//~^ NOTE assigned discriminant for `Last` was incremented from this discriminant
|
//~^ NOTE discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1)
|
||||||
Last,
|
Last,
|
||||||
//~^ NOTE second assignment of `-1`
|
//~^ NOTE `-1` assigned here
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MultipleDuplicates {
|
||||||
|
//~^ ERROR discriminant value `0` assigned more than once
|
||||||
|
//~^^ ERROR discriminant value `-2` assigned more than once
|
||||||
|
V0,
|
||||||
|
//~^ NOTE `0` assigned here
|
||||||
|
V1 = 0,
|
||||||
|
//~^ NOTE `0` assigned here
|
||||||
|
V2,
|
||||||
|
V3,
|
||||||
|
V4 = 0,
|
||||||
|
//~^ NOTE `0` assigned here
|
||||||
|
V5 = -2,
|
||||||
|
//~^ NOTE discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0)
|
||||||
|
//~^^ NOTE `-2` assigned here
|
||||||
|
V6,
|
||||||
|
V7,
|
||||||
|
//~^ NOTE `0` assigned here
|
||||||
|
V8 = -3,
|
||||||
|
//~^ NOTE discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2)
|
||||||
|
V9,
|
||||||
|
//~^ NOTE `-2` assigned here
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -5,10 +5,10 @@ LL | enum Enum {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | P = 3,
|
LL | P = 3,
|
||||||
| - first assignment of `3`
|
| - `3` assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | X = 3,
|
LL | X = 3,
|
||||||
| - second assignment of `3`
|
| - `3` assigned here
|
||||||
|
|
||||||
error[E0081]: discriminant value `1` assigned more than once
|
error[E0081]: discriminant value `1` assigned more than once
|
||||||
--> $DIR/E0081.rs:11:1
|
--> $DIR/E0081.rs:11:1
|
||||||
|
@ -17,10 +17,10 @@ LL | enum EnumOverflowRepr {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | P = 257,
|
LL | P = 257,
|
||||||
| --- first assignment of `1` (overflowed from `257`)
|
| --- `1` (overflowed from `257`) assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | X = 513,
|
LL | X = 513,
|
||||||
| --- second assignment of `1` (overflowed from `513`)
|
| --- `1` (overflowed from `513`) assigned here
|
||||||
|
|
||||||
error[E0081]: discriminant value `-1` assigned more than once
|
error[E0081]: discriminant value `-1` assigned more than once
|
||||||
--> $DIR/E0081.rs:20:1
|
--> $DIR/E0081.rs:20:1
|
||||||
|
@ -29,14 +29,50 @@ LL | enum NegDisEnum {
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | First = -1,
|
LL | First = -1,
|
||||||
| -- first assignment of `-1`
|
| -- `-1` assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | Second = -2,
|
LL | Second = -2,
|
||||||
| ----------- assigned discriminant for `Last` was incremented from this discriminant
|
| ----------- discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1)
|
||||||
LL |
|
LL |
|
||||||
LL | Last,
|
LL | Last,
|
||||||
| ---- second assignment of `-1`
|
| ---- `-1` assigned here
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0081]: discriminant value `0` assigned more than once
|
||||||
|
--> $DIR/E0081.rs:30:1
|
||||||
|
|
|
||||||
|
LL | enum MultipleDuplicates {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | V0,
|
||||||
|
| -- `0` assigned here
|
||||||
|
LL |
|
||||||
|
LL | V1 = 0,
|
||||||
|
| - `0` assigned here
|
||||||
|
...
|
||||||
|
LL | V4 = 0,
|
||||||
|
| - `0` assigned here
|
||||||
|
LL |
|
||||||
|
LL | V5 = -2,
|
||||||
|
| ------- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0)
|
||||||
|
...
|
||||||
|
LL | V7,
|
||||||
|
| -- `0` assigned here
|
||||||
|
|
||||||
|
error[E0081]: discriminant value `-2` assigned more than once
|
||||||
|
--> $DIR/E0081.rs:30:1
|
||||||
|
|
|
||||||
|
LL | enum MultipleDuplicates {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | V5 = -2,
|
||||||
|
| -- `-2` assigned here
|
||||||
|
...
|
||||||
|
LL | V8 = -3,
|
||||||
|
| ------- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2)
|
||||||
|
LL |
|
||||||
|
LL | V9,
|
||||||
|
| -- `-2` assigned here
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0081`.
|
For more information about this error, try `rustc --explain E0081`.
|
||||||
|
|
|
@ -38,9 +38,13 @@ fn main() {
|
||||||
let v = Unit2.m(
|
let v = Unit2.m(
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR type mismatch
|
||||||
L {
|
L {
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4`
|
||||||
f : |x| { drop(x); Unit4 }
|
f: |x| {
|
||||||
});
|
drop(x);
|
||||||
|
Unit4
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Ty<'a> for Unit2 {
|
impl<'a> Ty<'a> for Unit2 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
|
error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
|
||||||
--> $DIR/issue-62203-hrtb-ice.rs:38:19
|
--> $DIR/issue-62203-hrtb-ice.rs:38:19
|
||||||
|
|
|
|
||||||
LL | let v = Unit2.m(
|
LL | let v = Unit2.m(
|
||||||
| ^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
|
| ^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
|
||||||
|
|
|
|
||||||
note: expected this to be `<_ as Ty<'_>>::V`
|
note: expected this to be `<_ as Ty<'_>>::V`
|
||||||
--> $DIR/issue-62203-hrtb-ice.rs:21:14
|
--> $DIR/issue-62203-hrtb-ice.rs:21:14
|
||||||
|
@ -22,7 +22,7 @@ LL | where
|
||||||
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
|
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
|
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20] as FnOnce<((&'r u8,),)>>::Output == Unit3`
|
error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
|
||||||
--> $DIR/issue-62203-hrtb-ice.rs:40:9
|
--> $DIR/issue-62203-hrtb-ice.rs:40:9
|
||||||
|
|
|
|
||||||
LL | let v = Unit2.m(
|
LL | let v = Unit2.m(
|
||||||
|
@ -30,11 +30,14 @@ LL | let v = Unit2.m(
|
||||||
LL |
|
LL |
|
||||||
LL | / L {
|
LL | / L {
|
||||||
LL | |
|
LL | |
|
||||||
LL | | f : |x| { drop(x); Unit4 }
|
LL | | f: |x| {
|
||||||
LL | | });
|
LL | | drop(x);
|
||||||
|
LL | | Unit4
|
||||||
|
LL | | },
|
||||||
|
LL | | },
|
||||||
| |_________^ expected struct `Unit3`, found struct `Unit4`
|
| |_________^ expected struct `Unit3`, found struct `Unit4`
|
||||||
|
|
|
|
||||||
note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]>`
|
note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>`
|
||||||
--> $DIR/issue-62203-hrtb-ice.rs:17:16
|
--> $DIR/issue-62203-hrtb-ice.rs:17:16
|
||||||
|
|
|
|
||||||
LL | impl<'a, A, T> T0<'a, A> for L<T>
|
LL | impl<'a, A, T> T0<'a, A> for L<T>
|
||||||
|
|
|
@ -7,7 +7,7 @@ type F = impl core::future::Future<Output = u8>;
|
||||||
struct Bug {
|
struct Bug {
|
||||||
V1: [(); {
|
V1: [(); {
|
||||||
fn concrete_use() -> F {
|
fn concrete_use() -> F {
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
|
||||||
async {}
|
async {}
|
||||||
}
|
}
|
||||||
let f: F = async { 1 };
|
let f: F = async { 1 };
|
||||||
|
|
|
@ -16,7 +16,7 @@ LL | let f: F = async { 1 };
|
||||||
LL | }],
|
LL | }],
|
||||||
| - value is dropped here
|
| - value is dropped here
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<impl Future<Output = ()> as Future>::Output == u8`
|
error[E0271]: expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
|
||||||
--> $DIR/issue-78722.rs:9:30
|
--> $DIR/issue-78722.rs:9:30
|
||||||
|
|
|
|
||||||
LL | fn concrete_use() -> F {
|
LL | fn concrete_use() -> F {
|
||||||
|
|
|
@ -27,7 +27,7 @@ fn baz(n: bool) -> i32 {
|
||||||
|
|
||||||
const fn return_ty_mismatch() {
|
const fn return_ty_mismatch() {
|
||||||
const_eval_select((1,), foo, bar);
|
const_eval_select((1,), foo, bar);
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn args_ty_mismatch() {
|
const fn args_ty_mismatch() {
|
||||||
|
|
|
@ -51,7 +51,7 @@ note: required by a bound in `const_eval_select`
|
||||||
LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
|
LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32`
|
error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
|
||||||
--> $DIR/const-eval-select-bad.rs:29:5
|
--> $DIR/const-eval-select-bad.rs:29:5
|
||||||
|
|
|
|
||||||
LL | const_eval_select((1,), foo, bar);
|
LL | const_eval_select((1,), foo, bar);
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
const N: isize = 1;
|
|
||||||
|
|
||||||
enum Foo {
|
|
||||||
//~^ ERROR discriminant value `1` assigned more than once
|
|
||||||
//~| ERROR discriminant value `1` assigned more than once
|
|
||||||
//~| ERROR discriminant value `1` assigned more than once
|
|
||||||
A = 1,
|
|
||||||
B = 1,
|
|
||||||
C = 0,
|
|
||||||
D,
|
|
||||||
|
|
||||||
E = N,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,40 +0,0 @@
|
||||||
error[E0081]: discriminant value `1` assigned more than once
|
|
||||||
--> $DIR/issue-15524.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum Foo {
|
|
||||||
| ^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | A = 1,
|
|
||||||
| - first assignment of `1`
|
|
||||||
LL | B = 1,
|
|
||||||
| - second assignment of `1`
|
|
||||||
|
|
||||||
error[E0081]: discriminant value `1` assigned more than once
|
|
||||||
--> $DIR/issue-15524.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum Foo {
|
|
||||||
| ^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | A = 1,
|
|
||||||
| - first assignment of `1`
|
|
||||||
LL | B = 1,
|
|
||||||
LL | C = 0,
|
|
||||||
| ----- assigned discriminant for `D` was incremented from this discriminant
|
|
||||||
LL | D,
|
|
||||||
| - second assignment of `1`
|
|
||||||
|
|
||||||
error[E0081]: discriminant value `1` assigned more than once
|
|
||||||
--> $DIR/issue-15524.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum Foo {
|
|
||||||
| ^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | A = 1,
|
|
||||||
| - first assignment of `1`
|
|
||||||
...
|
|
||||||
LL | E = N,
|
|
||||||
| - second assignment of `1`
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0081`.
|
|
|
@ -3,12 +3,13 @@ use std::vec::IntoIter;
|
||||||
pub fn get_tok(it: &mut IntoIter<u8>) {
|
pub fn get_tok(it: &mut IntoIter<u8>) {
|
||||||
let mut found_e = false;
|
let mut found_e = false;
|
||||||
|
|
||||||
let temp: Vec<u8> = it.take_while(|&x| {
|
let temp: Vec<u8> = it
|
||||||
found_e = true;
|
.take_while(|&x| {
|
||||||
false
|
found_e = true;
|
||||||
})
|
false
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
//~^ ERROR type mismatch resolving
|
//~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
|
||||||
.collect(); //~ ERROR the method
|
.collect(); //~ ERROR the method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]> as Iterator>::Item == &_`
|
error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8`
|
||||||
--> $DIR/issue-31173.rs:10:10
|
--> $DIR/issue-31173.rs:11:10
|
||||||
|
|
|
|
||||||
LL | .cloned()
|
LL | .cloned()
|
||||||
| ^^^^^^ expected reference, found `u8`
|
| ^^^^^^ expected reference, found `u8`
|
||||||
|
@ -12,11 +12,11 @@ note: required by a bound in `cloned`
|
||||||
LL | Self: Sized + Iterator<Item = &'a T>,
|
LL | Self: Sized + Iterator<Item = &'a T>,
|
||||||
| ^^^^^^^^^^^^ required by this bound in `cloned`
|
| ^^^^^^^^^^^^ required by this bound in `cloned`
|
||||||
|
|
||||||
error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>`, but its trait bounds were not satisfied
|
error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied
|
||||||
--> $DIR/issue-31173.rs:12:10
|
--> $DIR/issue-31173.rs:13:10
|
||||||
|
|
|
|
||||||
LL | .collect();
|
LL | .collect();
|
||||||
| ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>` due to unsatisfied trait bounds
|
| ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds
|
||||||
|
|
|
|
||||||
::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
|
::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
|
||||||
|
|
|
|
||||||
|
@ -29,10 +29,10 @@ LL | pub struct TakeWhile<I, P> {
|
||||||
| -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
|
| -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
|
||||||
|
|
|
|
||||||
= note: the following trait bounds were not satisfied:
|
= note: the following trait bounds were not satisfied:
|
||||||
`<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]> as Iterator>::Item = &_`
|
`<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
|
||||||
which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator`
|
which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
|
||||||
`Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator`
|
`Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
|
||||||
which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator`
|
which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
|
for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
//~| ERROR type mismatch
|
//~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
|
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
--> $DIR/issue-33941.rs:6:36
|
--> $DIR/issue-33941.rs:6:36
|
||||||
|
|
|
|
||||||
LL | for _ in HashMap::new().iter().cloned() {}
|
LL | for _ in HashMap::new().iter().cloned() {}
|
||||||
|
@ -12,7 +12,7 @@ note: required by a bound in `cloned`
|
||||||
LL | Self: Sized + Iterator<Item = &'a T>,
|
LL | Self: Sized + Iterator<Item = &'a T>,
|
||||||
| ^^^^^^^^^^^^ required by this bound in `cloned`
|
| ^^^^^^^^^^^^ required by this bound in `cloned`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
|
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
--> $DIR/issue-33941.rs:6:14
|
--> $DIR/issue-33941.rs:6:14
|
||||||
|
|
|
|
||||||
LL | for _ in HashMap::new().iter().cloned() {}
|
LL | for _ in HashMap::new().iter().cloned() {}
|
||||||
|
@ -23,7 +23,7 @@ LL | for _ in HashMap::new().iter().cloned() {}
|
||||||
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
||||||
= note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
= note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
|
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||||
--> $DIR/issue-33941.rs:6:14
|
--> $DIR/issue-33941.rs:6:14
|
||||||
|
|
|
|
||||||
LL | for _ in HashMap::new().iter().cloned() {}
|
LL | for _ in HashMap::new().iter().cloned() {}
|
||||||
|
|
18
src/test/ui/macros/auxiliary/issue-100199.rs
Normal file
18
src/test/ui/macros/auxiliary/issue-100199.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// force-host
|
||||||
|
// no-prefer-dynamic
|
||||||
|
|
||||||
|
#![crate_type = "proc-macro"]
|
||||||
|
#![feature(proc_macro_quote)]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::{quote, Ident, Span, TokenStream, TokenTree};
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn struct_with_bound(_: TokenStream, _: TokenStream) -> TokenStream {
|
||||||
|
let crate_ident = TokenTree::Ident(Ident::new("crate", Span::call_site()));
|
||||||
|
let trait_ident = TokenTree::Ident(Ident::new("MyTrait", Span::call_site()));
|
||||||
|
quote!(
|
||||||
|
struct Foo<T: $crate_ident::$trait_ident> {}
|
||||||
|
)
|
||||||
|
}
|
16
src/test/ui/macros/issue-100199.rs
Normal file
16
src/test/ui/macros/issue-100199.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#[issue_100199::struct_with_bound] //~ ERROR cannot find trait `MyTrait` in the crate root
|
||||||
|
struct Foo {}
|
||||||
|
// The above must be on the first line so that it's span points to pos 0.
|
||||||
|
// This used to trigger an ICE because the diagnostic emitter would get
|
||||||
|
// an unexpected dummy span (lo == 0 == hi) while attempting to print a
|
||||||
|
// suggestion.
|
||||||
|
|
||||||
|
// aux-build: issue-100199.rs
|
||||||
|
|
||||||
|
extern crate issue_100199;
|
||||||
|
|
||||||
|
mod traits {
|
||||||
|
pub trait MyTrait {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
15
src/test/ui/macros/issue-100199.stderr
Normal file
15
src/test/ui/macros/issue-100199.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0405]: cannot find trait `MyTrait` in the crate root
|
||||||
|
--> $DIR/issue-100199.rs:1:1
|
||||||
|
|
|
||||||
|
LL | #[issue_100199::struct_with_bound]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root
|
||||||
|
|
|
||||||
|
= note: this error originates in the attribute macro `issue_100199::struct_with_bound` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider importing this trait
|
||||||
|
|
|
||||||
|
LL | use traits::MyTrait;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0405`.
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47] as FnOnce<()>>::Output == ()`
|
error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
|
||||||
--> $DIR/fallback-closure-wrap.rs:18:31
|
--> $DIR/fallback-closure-wrap.rs:18:31
|
||||||
|
|
|
|
||||||
LL | let error = Closure::wrap(Box::new(move || {
|
LL | let error = Closure::wrap(Box::new(move || {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let error = Closure::wrap(Box::new(move || {
|
let error = Closure::wrap(Box::new(move || {
|
||||||
//[fallback]~^ ERROR type mismatch resolving
|
//[fallback]~^ to be a closure that returns `()`, but it returns `!`
|
||||||
panic!("Can't connect to server.");
|
panic!("Can't connect to server.");
|
||||||
}) as Box<dyn FnMut()>);
|
}) as Box<dyn FnMut()>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered
|
||||||
|
Some(1) => {}
|
||||||
|
// hello
|
||||||
|
Some(_) => {}
|
||||||
|
None => todo!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered
|
||||||
|
Some(1) => {}
|
||||||
|
// hello
|
||||||
|
Some(_) => {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
error[E0004]: non-exhaustive patterns: `None` not covered
|
||||||
|
--> $DIR/suggest-adding-appropriate-missing-pattern-excluding-comments.rs:4:11
|
||||||
|
|
|
||||||
|
LL | match Some(1) {
|
||||||
|
| ^^^^^^^ pattern `None` not covered
|
||||||
|
|
|
||||||
|
note: `Option<i32>` defined here
|
||||||
|
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub enum Option<T> {
|
||||||
|
| ------------------
|
||||||
|
...
|
||||||
|
LL | None,
|
||||||
|
| ^^^^ not covered
|
||||||
|
= note: the matched value is of type `Option<i32>`
|
||||||
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
||||||
|
LL ~ Some(_) => {}
|
||||||
|
LL + None => todo!()
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0004`.
|
19
src/test/ui/proc-macro/auxiliary/re-export.rs
Normal file
19
src/test/ui/proc-macro/auxiliary/re-export.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// force-host
|
||||||
|
// no-prefer-dynamic
|
||||||
|
|
||||||
|
#![crate_type = "proc-macro"]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn cause_ice(_: TokenStream) -> TokenStream {
|
||||||
|
"
|
||||||
|
enum IceCause {
|
||||||
|
Variant,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use IceCause::Variant;
|
||||||
|
".parse().unwrap()
|
||||||
|
}
|
10
src/test/ui/proc-macro/issue-79148.rs
Normal file
10
src/test/ui/proc-macro/issue-79148.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// aux-build:re-export.rs
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
extern crate re_export;
|
||||||
|
|
||||||
|
use re_export::cause_ice;
|
||||||
|
|
||||||
|
cause_ice!(); //~ ERROR `Variant` is only public within the crate, and cannot be re-exported outside
|
||||||
|
|
||||||
|
fn main() {}
|
16
src/test/ui/proc-macro/issue-79148.stderr
Normal file
16
src/test/ui/proc-macro/issue-79148.stderr
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
error[E0364]: `Variant` is only public within the crate, and cannot be re-exported outside
|
||||||
|
--> $DIR/issue-79148.rs:8:1
|
||||||
|
|
|
||||||
|
LL | cause_ice!();
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: consider marking `Variant` as `pub` in the imported module
|
||||||
|
--> $DIR/issue-79148.rs:8:1
|
||||||
|
|
|
||||||
|
LL | cause_ice!();
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
= note: this error originates in the macro `cause_ice` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0364`.
|
29
src/test/ui/stability-attribute/auxiliary/default_body.rs
Normal file
29
src/test/ui/stability-attribute/auxiliary/default_body.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(staged_api, rustc_attrs)]
|
||||||
|
#![stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
pub trait JustTrait {
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
#[rustc_default_body_unstable(feature = "constant_default_body", issue = "none")]
|
||||||
|
const CONSTANT: usize = 0;
|
||||||
|
|
||||||
|
#[rustc_default_body_unstable(feature = "fun_default_body", issue = "none")]
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
fn fun() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_must_implement_one_of(eq, neq)]
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
pub trait Equal {
|
||||||
|
#[rustc_default_body_unstable(feature = "eq_default_body", issue = "none")]
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
!self.neq(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "stable_feature", since = "1.0.0")]
|
||||||
|
fn neq(&self, other: &Self) -> bool {
|
||||||
|
!self.eq(other)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// aux-build:default_body.rs
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
extern crate default_body;
|
||||||
|
|
||||||
|
use default_body::{Equal, JustTrait};
|
||||||
|
|
||||||
|
struct Type;
|
||||||
|
|
||||||
|
impl JustTrait for Type {}
|
||||||
|
//~^ ERROR not all trait items implemented, missing: `CONSTANT` [E0046]
|
||||||
|
//~| ERROR not all trait items implemented, missing: `fun` [E0046]
|
||||||
|
|
||||||
|
impl Equal for Type {
|
||||||
|
//~^ ERROR not all trait items implemented, missing: `eq` [E0046]
|
||||||
|
fn neq(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
error[E0046]: not all trait items implemented, missing: `CONSTANT`
|
||||||
|
--> $DIR/default-body-stability-err.rs:10:1
|
||||||
|
|
|
||||||
|
LL | impl JustTrait for Type {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: default implementation of `CONSTANT` is unstable
|
||||||
|
= note: use of unstable library feature 'constant_default_body'
|
||||||
|
= help: add `#![feature(constant_default_body)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0046]: not all trait items implemented, missing: `fun`
|
||||||
|
--> $DIR/default-body-stability-err.rs:10:1
|
||||||
|
|
|
||||||
|
LL | impl JustTrait for Type {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: default implementation of `fun` is unstable
|
||||||
|
= note: use of unstable library feature 'fun_default_body'
|
||||||
|
= help: add `#![feature(fun_default_body)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0046]: not all trait items implemented, missing: `eq`
|
||||||
|
--> $DIR/default-body-stability-err.rs:14:1
|
||||||
|
|
|
||||||
|
LL | / impl Equal for Type {
|
||||||
|
LL | |
|
||||||
|
LL | | fn neq(&self, other: &Self) -> bool {
|
||||||
|
LL | | false
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
= note: default implementation of `eq` is unstable
|
||||||
|
= note: use of unstable library feature 'eq_default_body'
|
||||||
|
= help: add `#![feature(eq_default_body)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0046`.
|
|
@ -0,0 +1,18 @@
|
||||||
|
// check-pass
|
||||||
|
// aux-build:default_body.rs
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(fun_default_body, eq_default_body, constant_default_body)]
|
||||||
|
|
||||||
|
extern crate default_body;
|
||||||
|
|
||||||
|
use default_body::{Equal, JustTrait};
|
||||||
|
|
||||||
|
struct Type;
|
||||||
|
|
||||||
|
impl JustTrait for Type {}
|
||||||
|
|
||||||
|
impl Equal for Type {
|
||||||
|
fn neq(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
// check-pass
|
||||||
|
// aux-build:default_body.rs
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
extern crate default_body;
|
||||||
|
|
||||||
|
use default_body::{Equal, JustTrait};
|
||||||
|
|
||||||
|
struct Type;
|
||||||
|
|
||||||
|
impl JustTrait for Type {
|
||||||
|
const CONSTANT: usize = 1;
|
||||||
|
|
||||||
|
fn fun() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Equal for Type {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
// Black and White have the same discriminator value ...
|
|
||||||
|
|
||||||
enum Color {
|
|
||||||
//~^ ERROR discriminant value `0` assigned more than once
|
|
||||||
Red = 0xff0000,
|
|
||||||
Green = 0x00ff00,
|
|
||||||
Blue = 0x0000ff,
|
|
||||||
Black = 0x000000,
|
|
||||||
White = 0x000000,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() { }
|
|
|
@ -1,14 +0,0 @@
|
||||||
error[E0081]: discriminant value `0` assigned more than once
|
|
||||||
--> $DIR/tag-variant-disr-dup.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum Color {
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | Black = 0x000000,
|
|
||||||
| -------- first assignment of `0`
|
|
||||||
LL | White = 0x000000,
|
|
||||||
| -------- second assignment of `0`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0081`.
|
|
|
@ -4,13 +4,13 @@
|
||||||
|
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
|
pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
|
||||||
type Key;
|
type Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for IntoIter<i32> {
|
impl Foo for IntoIter<i32> {
|
||||||
type Key = u32; //~ ERROR type mismatch
|
type Key = u32;
|
||||||
|
//~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<i32> as Iterator>::Item == u32`
|
error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||||
--> $DIR/assoc-type-in-superbad.rs:12:16
|
--> $DIR/assoc-type-in-superbad.rs:12:16
|
||||||
|
|
|
|
||||||
LL | type Key = u32;
|
LL | type Key = u32;
|
||||||
|
@ -7,8 +7,8 @@ LL | type Key = u32;
|
||||||
note: required by a bound in `Foo`
|
note: required by a bound in `Foo`
|
||||||
--> $DIR/assoc-type-in-superbad.rs:7:25
|
--> $DIR/assoc-type-in-superbad.rs:7:25
|
||||||
|
|
|
|
||||||
LL | pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
|
LL | pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ trait Foo {
|
||||||
|
|
||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
type Bar = std::vec::IntoIter<u32>;
|
type Bar = std::vec::IntoIter<u32>;
|
||||||
//~^ ERROR type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X
|
//~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn incoherent() {
|
fn incoherent() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X`
|
error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||||
--> $DIR/issue-57961.rs:10:16
|
--> $DIR/issue-57961.rs:10:16
|
||||||
|
|
|
|
||||||
LL | type X = impl Sized;
|
LL | type X = impl Sized;
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
type AsyncFnPtr = Box<
|
type AsyncFnPtr = Box<dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>>;
|
||||||
dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
async fn test() {}
|
async fn test() {}
|
||||||
|
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
fn main() {
|
fn main() {
|
||||||
Box::new(test) as AsyncFnPtr;
|
Box::new(test) as AsyncFnPtr;
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0271]: type mismatch resolving `<fn() -> impl Future<Output = ()> {test} as FnOnce<()>>::Output == Pin<Box<(dyn Future<Output = ()> + 'static)>>`
|
error[E0271]: expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
|
||||||
--> $DIR/issue-98604.rs:11:5
|
--> $DIR/issue-98604.rs:9:5
|
||||||
|
|
|
|
||||||
LL | Box::new(test) as AsyncFnPtr;
|
LL | Box::new(test) as AsyncFnPtr;
|
||||||
| ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
|
| ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
|
||||||
|
|
|
|
||||||
note: while checking the return type of the `async fn`
|
note: while checking the return type of the `async fn`
|
||||||
--> $DIR/issue-98604.rs:7:17
|
--> $DIR/issue-98604.rs:5:17
|
||||||
|
|
|
|
||||||
LL | async fn test() {}
|
LL | async fn test() {}
|
||||||
| ^ checked the `Output` of this `async fn`, found opaque type
|
| ^ checked the `Output` of this `async fn`, found opaque type
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
fn hi() -> impl Sized { std::ptr::null::<u8>() }
|
fn hi() -> impl Sized {
|
||||||
|
std::ptr::null::<u8>()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
|
let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
|
||||||
//~^ ERROR type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
|
//~^ ERROR expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
|
||||||
let boxed = b();
|
let boxed = b();
|
||||||
let null = *boxed;
|
let null = *boxed;
|
||||||
println!("{null:?}");
|
println!("{null:?}");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error[E0271]: type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
|
error[E0271]: expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
|
||||||
--> $DIR/issue-98608.rs:4:39
|
--> $DIR/issue-98608.rs:6:39
|
||||||
|
|
|
|
||||||
LL | fn hi() -> impl Sized { std::ptr::null::<u8>() }
|
LL | fn hi() -> impl Sized {
|
||||||
| ---------- the found opaque type
|
| ---------- the found opaque type
|
||||||
...
|
...
|
||||||
LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
|
LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
|
||||||
|
|
|
@ -2,9 +2,12 @@ error[E0615]: attempted to take value of method `read` on type `*mut Foo`
|
||||||
--> $DIR/issue-91210-ptr-method.rs:10:7
|
--> $DIR/issue-91210-ptr-method.rs:10:7
|
||||||
|
|
|
|
||||||
LL | x.read = 4;
|
LL | x.read = 4;
|
||||||
| - ^^^^ method, not a field
|
| ^^^^ method, not a field
|
||||||
| |
|
|
|
||||||
| help: to access the field, dereference first: `(*x)`
|
help: to access the field, dereference first
|
||||||
|
|
|
||||||
|
LL | (*x).read = 4;
|
||||||
|
| ++ +
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ Before submitting, please make sure that you're not running into one of these kn
|
||||||
Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
|
Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**rust-analyzer version**: (eg. output of "Rust Analyzer: Show RA Version" command)
|
**rust-analyzer version**: (eg. output of "rust-analyzer: Show RA Version" command, accessible in VSCode via <kbd>Ctrl/⌘</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>)
|
||||||
|
|
||||||
**rustc version**: (eg. output of `rustc -V`)
|
**rustc version**: (eg. output of `rustc -V`)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ env:
|
||||||
FETCH_DEPTH: 0 # pull in the tags for the version string
|
FETCH_DEPTH: 0 # pull in the tags for the version string
|
||||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||||
|
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
dist:
|
dist:
|
||||||
|
@ -36,6 +37,9 @@ jobs:
|
||||||
- os: ubuntu-18.04
|
- os: ubuntu-18.04
|
||||||
target: aarch64-unknown-linux-gnu
|
target: aarch64-unknown-linux-gnu
|
||||||
code-target: linux-arm64
|
code-target: linux-arm64
|
||||||
|
- os: ubuntu-18.04
|
||||||
|
target: arm-unknown-linux-gnueabihf
|
||||||
|
code-target: linux-armhf
|
||||||
- os: macos-11
|
- os: macos-11
|
||||||
target: x86_64-apple-darwin
|
target: x86_64-apple-darwin
|
||||||
code-target: darwin-x64
|
code-target: darwin-x64
|
||||||
|
@ -67,13 +71,17 @@ jobs:
|
||||||
node-version: 14.x
|
node-version: 14.x
|
||||||
|
|
||||||
- name: Update apt repositories
|
- name: Update apt repositories
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf'
|
||||||
run: sudo apt-get update
|
run: sudo apt-get update
|
||||||
|
|
||||||
- name: Install target toolchain
|
- name: Install AArch64 target toolchain
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||||
run: sudo apt-get install gcc-aarch64-linux-gnu
|
run: sudo apt-get install gcc-aarch64-linux-gnu
|
||||||
|
|
||||||
|
- name: Install ARM target toolchain
|
||||||
|
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
||||||
|
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
||||||
|
|
||||||
- name: Dist
|
- name: Dist
|
||||||
run: cargo xtask dist --client-patch-version ${{ github.run_number }}
|
run: cargo xtask dist --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
|
@ -204,6 +212,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: dist-aarch64-unknown-linux-gnu
|
name: dist-aarch64-unknown-linux-gnu
|
||||||
path: dist
|
path: dist
|
||||||
|
- uses: actions/download-artifact@v1
|
||||||
|
with:
|
||||||
|
name: dist-arm-unknown-linux-gnueabihf
|
||||||
|
path: dist
|
||||||
- uses: actions/download-artifact@v1
|
- uses: actions/download-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: dist-x86_64-pc-windows-msvc
|
name: dist-x86_64-pc-windows-msvc
|
||||||
|
|
|
@ -43,7 +43,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Rust analyzer is primarily distributed under the terms of both the MIT
|
rust-analyzer is primarily distributed under the terms of both the MIT
|
||||||
license and the Apache License (Version 2.0).
|
license and the Apache License (Version 2.0).
|
||||||
|
|
||||||
See LICENSE-APACHE and LICENSE-MIT for details.
|
See LICENSE-APACHE and LICENSE-MIT for details.
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub struct FlycheckHandle {
|
||||||
// XXX: drop order is significant
|
// XXX: drop order is significant
|
||||||
sender: Sender<Restart>,
|
sender: Sender<Restart>,
|
||||||
_thread: jod_thread::JoinHandle,
|
_thread: jod_thread::JoinHandle,
|
||||||
|
id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlycheckHandle {
|
impl FlycheckHandle {
|
||||||
|
@ -72,18 +73,22 @@ impl FlycheckHandle {
|
||||||
.name("Flycheck".to_owned())
|
.name("Flycheck".to_owned())
|
||||||
.spawn(move || actor.run(receiver))
|
.spawn(move || actor.run(receiver))
|
||||||
.expect("failed to spawn thread");
|
.expect("failed to spawn thread");
|
||||||
FlycheckHandle { sender, _thread: thread }
|
FlycheckHandle { id, sender, _thread: thread }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule a re-start of the cargo check worker.
|
/// Schedule a re-start of the cargo check worker.
|
||||||
pub fn update(&self) {
|
pub fn update(&self) {
|
||||||
self.sender.send(Restart).unwrap();
|
self.sender.send(Restart).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> usize {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
/// Request adding a diagnostic with fixes included to a file
|
/// Request adding a diagnostic with fixes included to a file
|
||||||
AddDiagnostic { workspace_root: AbsPathBuf, diagnostic: Diagnostic },
|
AddDiagnostic { id: usize, workspace_root: AbsPathBuf, diagnostic: Diagnostic },
|
||||||
|
|
||||||
/// Request check progress notification to client
|
/// Request check progress notification to client
|
||||||
Progress {
|
Progress {
|
||||||
|
@ -96,8 +101,9 @@ pub enum Message {
|
||||||
impl fmt::Debug for Message {
|
impl fmt::Debug for Message {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Message::AddDiagnostic { workspace_root, diagnostic } => f
|
Message::AddDiagnostic { id, workspace_root, diagnostic } => f
|
||||||
.debug_struct("AddDiagnostic")
|
.debug_struct("AddDiagnostic")
|
||||||
|
.field("id", id)
|
||||||
.field("workspace_root", workspace_root)
|
.field("workspace_root", workspace_root)
|
||||||
.field("diagnostic_code", &diagnostic.code.as_ref().map(|it| &it.code))
|
.field("diagnostic_code", &diagnostic.code.as_ref().map(|it| &it.code))
|
||||||
.finish(),
|
.finish(),
|
||||||
|
@ -183,7 +189,7 @@ impl FlycheckActor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::CheckEvent(None) => {
|
Event::CheckEvent(None) => {
|
||||||
tracing::debug!("flycheck finished");
|
tracing::debug!(flycheck_id = self.id, "flycheck finished");
|
||||||
|
|
||||||
// Watcher finished
|
// Watcher finished
|
||||||
let cargo_handle = self.cargo_handle.take().unwrap();
|
let cargo_handle = self.cargo_handle.take().unwrap();
|
||||||
|
@ -203,6 +209,7 @@ impl FlycheckActor {
|
||||||
|
|
||||||
CargoMessage::Diagnostic(msg) => {
|
CargoMessage::Diagnostic(msg) => {
|
||||||
self.send(Message::AddDiagnostic {
|
self.send(Message::AddDiagnostic {
|
||||||
|
id: self.id,
|
||||||
workspace_root: self.workspace_root.clone(),
|
workspace_root: self.workspace_root.clone(),
|
||||||
diagnostic: msg,
|
diagnostic: msg,
|
||||||
});
|
});
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue