Auto merge of #149941 - jhpratt:rollup-9p1xc2t, r=jhpratt
Rollup of 10 pull requests Successful merges: - rust-lang/rust#145278 (Update `rustc_codegen_gcc` rotate operation document) - rust-lang/rust#148837 (Use `let...else` instead of `match foo { ... _ => return };` and `if let ... else return`) - rust-lang/rust#149177 (Add proper suggestion for associated function with unknown field) - rust-lang/rust#149843 (Inherit attributes in delegation) - rust-lang/rust#149860 (Fix: Prevent macro-expanded extern crates from shadowing extern arguments) - rust-lang/rust#149874 (Weak for Arc pointer is marked as DynSend/DynSync) - rust-lang/rust#149903 (Remove unused code in `cfg_old`) - rust-lang/rust#149911 (bootstrap: Don't pass an unused `--color` to compiletest) - rust-lang/rust#149916 (Add a sanity check in case of any duplicate nodes) - rust-lang/rust#149924 (`declare_lint_pass` for `INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ce63e5d9ea
85 changed files with 904 additions and 846 deletions
|
|
@ -1533,11 +1533,10 @@ impl Expr {
|
|||
// then type of result is trait object.
|
||||
// Otherwise we don't assume the result type.
|
||||
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
|
||||
if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
|
||||
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
|
||||
} else {
|
||||
let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
|
||||
}
|
||||
|
||||
ExprKind::Underscore => TyKind::Infer,
|
||||
|
|
|
|||
|
|
@ -447,20 +447,17 @@ impl MetaItem {
|
|||
thin_vec![PathSegment::path_root(span)]
|
||||
};
|
||||
loop {
|
||||
if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
|
||||
let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
|
||||
iter.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
|
||||
{
|
||||
segments.push(PathSegment::from_ident(Ident::new(name, span)));
|
||||
} else {
|
||||
else {
|
||||
return None;
|
||||
}
|
||||
if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
|
||||
iter.peek()
|
||||
{
|
||||
iter.next();
|
||||
} else {
|
||||
};
|
||||
segments.push(PathSegment::from_ident(Ident::new(name, span)));
|
||||
let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = iter.peek()
|
||||
else {
|
||||
break;
|
||||
}
|
||||
};
|
||||
iter.next();
|
||||
}
|
||||
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
|
||||
Path { span, segments, tokens: None }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![doc(test(attr(deny(warnings), allow(internal_features))))]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
|
|
|
|||
|
|
@ -43,13 +43,15 @@ use hir::def::{DefKind, PartialRes, Res};
|
|||
use hir::{BodyId, HirId};
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::*;
|
||||
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::Target;
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
|
||||
use rustc_middle::ty::{Asyncness, DelegationFnSigAttrs, ResolverAstLowering};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
|
||||
|
|
@ -62,6 +64,41 @@ pub(crate) struct DelegationResults<'hir> {
|
|||
pub generics: &'hir hir::Generics<'hir>,
|
||||
}
|
||||
|
||||
struct AttributeAdditionInfo {
|
||||
pub equals: fn(&hir::Attribute) -> bool,
|
||||
pub kind: AttributeAdditionKind,
|
||||
}
|
||||
|
||||
enum AttributeAdditionKind {
|
||||
Default { factory: fn(Span) -> hir::Attribute },
|
||||
Inherit { flag: DelegationFnSigAttrs, factory: fn(Span, &hir::Attribute) -> hir::Attribute },
|
||||
}
|
||||
|
||||
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
|
||||
|
||||
static ATTRIBUTES_ADDITIONS: &[AttributeAdditionInfo] = &[
|
||||
AttributeAdditionInfo {
|
||||
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })),
|
||||
kind: AttributeAdditionKind::Inherit {
|
||||
factory: |span, original_attribute| {
|
||||
let reason = match original_attribute {
|
||||
hir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => *reason,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
hir::Attribute::Parsed(AttributeKind::MustUse { span, reason })
|
||||
},
|
||||
flag: DelegationFnSigAttrs::MUST_USE,
|
||||
},
|
||||
},
|
||||
AttributeAdditionInfo {
|
||||
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))),
|
||||
kind: AttributeAdditionKind::Default {
|
||||
factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn is_method(&self, def_id: DefId, span: Span) -> bool {
|
||||
match self.tcx.def_kind(def_id) {
|
||||
|
|
@ -88,7 +125,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
|
||||
match sig_id {
|
||||
Ok(sig_id) => {
|
||||
self.add_inline_attribute_if_needed(span);
|
||||
self.add_attributes_if_needed(span, sig_id);
|
||||
|
||||
let is_method = self.is_method(sig_id, span);
|
||||
let (param_count, c_variadic) = self.param_count(sig_id);
|
||||
|
|
@ -103,29 +140,100 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_inline_attribute_if_needed(&mut self, span: Span) {
|
||||
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
|
||||
let create_inline_attr_slice =
|
||||
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];
|
||||
fn add_attributes_if_needed(&mut self, span: Span, sig_id: DefId) {
|
||||
let new_attributes = self.create_new_attributes(
|
||||
ATTRIBUTES_ADDITIONS,
|
||||
span,
|
||||
sig_id,
|
||||
self.attrs.get(&PARENT_ID),
|
||||
);
|
||||
|
||||
let new_attributes = match self.attrs.get(&PARENT_ID) {
|
||||
Some(attrs) => {
|
||||
// Check if reuse already specifies any inline attribute, if so, do nothing
|
||||
if attrs
|
||||
.iter()
|
||||
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if new_attributes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.arena.alloc_from_iter(
|
||||
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
|
||||
)
|
||||
}
|
||||
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
|
||||
let new_arena_allocated_attributes = match self.attrs.get(&PARENT_ID) {
|
||||
Some(existing_attrs) => self.arena.alloc_from_iter(
|
||||
existing_attrs.iter().map(|a| a.clone()).chain(new_attributes.into_iter()),
|
||||
),
|
||||
None => self.arena.alloc_from_iter(new_attributes.into_iter()),
|
||||
};
|
||||
|
||||
self.attrs.insert(PARENT_ID, new_attributes);
|
||||
self.attrs.insert(PARENT_ID, new_arena_allocated_attributes);
|
||||
}
|
||||
|
||||
fn create_new_attributes(
|
||||
&self,
|
||||
candidate_additions: &[AttributeAdditionInfo],
|
||||
span: Span,
|
||||
sig_id: DefId,
|
||||
existing_attrs: Option<&&[hir::Attribute]>,
|
||||
) -> Vec<hir::Attribute> {
|
||||
let local_original_attributes = self.parse_local_original_attributes(sig_id);
|
||||
|
||||
candidate_additions
|
||||
.iter()
|
||||
.filter_map(|addition_info| {
|
||||
if let Some(existing_attrs) = existing_attrs
|
||||
&& existing_attrs
|
||||
.iter()
|
||||
.any(|existing_attr| (addition_info.equals)(existing_attr))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
match addition_info.kind {
|
||||
AttributeAdditionKind::Default { factory } => Some(factory(span)),
|
||||
AttributeAdditionKind::Inherit { flag, factory } => {
|
||||
let original_attribute = match sig_id.as_local() {
|
||||
Some(local_id) => self
|
||||
.resolver
|
||||
.delegation_fn_sigs
|
||||
.get(&local_id)
|
||||
.is_some_and(|sig| sig.attrs_flags.contains(flag))
|
||||
.then(|| {
|
||||
local_original_attributes
|
||||
.as_ref()
|
||||
.map(|attrs| {
|
||||
attrs
|
||||
.iter()
|
||||
.find(|base_attr| (addition_info.equals)(base_attr))
|
||||
})
|
||||
.flatten()
|
||||
})
|
||||
.flatten(),
|
||||
None => self
|
||||
.tcx
|
||||
.get_all_attrs(sig_id)
|
||||
.iter()
|
||||
.find(|base_attr| (addition_info.equals)(base_attr)),
|
||||
};
|
||||
|
||||
original_attribute.map(|a| factory(span, a))
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn parse_local_original_attributes(&self, sig_id: DefId) -> Option<Vec<hir::Attribute>> {
|
||||
if let Some(local_id) = sig_id.as_local()
|
||||
&& let Some(info) = self.resolver.delegation_fn_sigs.get(&local_id)
|
||||
&& !info.to_inherit_attrs.is_empty()
|
||||
{
|
||||
Some(AttributeParser::parse_limited_all(
|
||||
self.tcx.sess,
|
||||
info.to_inherit_attrs.as_slice(),
|
||||
None,
|
||||
Target::Fn,
|
||||
DUMMY_SP,
|
||||
DUMMY_NODE_ID,
|
||||
Some(self.tcx.features()),
|
||||
ShouldEmit::Nothing,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_delegation_sig_id(
|
||||
|
|
@ -220,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
|
||||
// and here we need the hir attributes.
|
||||
let default_safety =
|
||||
if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod {
|
||||
if sig.attrs_flags.contains(DelegationFnSigAttrs::TARGET_FEATURE)
|
||||
|| self.tcx.def_kind(parent) == DefKind::ForeignMod
|
||||
{
|
||||
hir::Safety::Unsafe
|
||||
} else {
|
||||
hir::Safety::Safe
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ attr_parsing_bundle_needs_static =
|
|||
|
||||
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
|
||||
|
||||
attr_parsing_cfg_predicate_identifier =
|
||||
`cfg` predicate key must be an identifier
|
||||
|
||||
attr_parsing_deprecated_item_suggestion =
|
||||
suggestions on deprecated items are unstable
|
||||
.help = add `#![feature(deprecated_suggestion)]` to the crate root
|
||||
|
|
@ -41,9 +38,6 @@ attr_parsing_empty_link_name =
|
|||
link name must not be empty
|
||||
.label = empty link name
|
||||
|
||||
attr_parsing_expected_one_cfg_pattern =
|
||||
expected 1 cfg-pattern
|
||||
|
||||
attr_parsing_expected_single_version_literal =
|
||||
expected single version literal
|
||||
|
||||
|
|
@ -241,12 +235,6 @@ attr_parsing_unstable_cfg_target_compact =
|
|||
attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable
|
||||
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
|
||||
attr_parsing_unsupported_literal_cfg_boolean =
|
||||
literal in `cfg` predicate value must be a boolean
|
||||
attr_parsing_unsupported_literal_cfg_string =
|
||||
literal in `cfg` predicate value must be a string
|
||||
attr_parsing_unsupported_literal_generic =
|
||||
unsupported literal
|
||||
attr_parsing_unsupported_literal_suggestion =
|
||||
consider removing the prefix
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use rustc_ast::token::Delimiter;
|
|||
use rustc_ast::tokenstream::DelimSpan;
|
||||
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template};
|
||||
use rustc_feature::{
|
||||
AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template,
|
||||
};
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, RustcVersion};
|
||||
|
|
@ -23,7 +25,7 @@ use crate::session_diagnostics::{
|
|||
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
|
||||
ParsedDescription,
|
||||
};
|
||||
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics, try_gate_cfg};
|
||||
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics};
|
||||
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["predicate"],
|
||||
|
|
@ -410,3 +412,19 @@ fn parse_cfg_attr_internal<'a>(
|
|||
|
||||
Ok((cfg_predicate, expanded_attrs))
|
||||
}
|
||||
|
||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, explain).emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,210 +0,0 @@
|
|||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_hir::RustcVersion;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{BuiltinLintDiag, Lint};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
|
||||
use crate::{fluent_generated, parse_version};
|
||||
|
||||
/// Emitter of a builtin lint from `cfg_matches`.
|
||||
///
|
||||
/// Used to support emitting a lint (currently on check-cfg), either:
|
||||
/// - as an early buffered lint (in `rustc`)
|
||||
/// - or has a "normal" lint from HIR (in `rustdoc`)
|
||||
pub trait CfgMatchesLintEmitter {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag);
|
||||
}
|
||||
|
||||
impl CfgMatchesLintEmitter for NodeId {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) {
|
||||
sess.psess.buffer_lint(lint, sp, *self, diag);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Condition {
|
||||
pub name: Symbol,
|
||||
pub name_span: Span,
|
||||
pub value: Option<Symbol>,
|
||||
pub value_span: Option<Span>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
pub fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, explain).emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &MetaItemInner,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = sess.dcx();
|
||||
|
||||
let cfg = match cfg {
|
||||
MetaItemInner::MetaItem(meta_item) => meta_item,
|
||||
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
|
||||
return *b;
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: cfg.span(),
|
||||
reason: UnsupportedLiteralReason::CfgBoolean,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(cfg.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match &cfg.kind {
|
||||
MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
let (min_version, span) = match &mis[..] {
|
||||
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||
(sym, span)
|
||||
}
|
||||
[
|
||||
MetaItemInner::Lit(MetaItemLit { span, .. })
|
||||
| MetaItemInner::MetaItem(MetaItem { span, .. }),
|
||||
] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
||||
return false;
|
||||
}
|
||||
[..] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
||||
span: cfg.span,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let Some(min_version) = parse_version(*min_version) else {
|
||||
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||
return false;
|
||||
};
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::current_overridable() > min_version
|
||||
} else {
|
||||
RustcVersion::current_overridable() >= min_version
|
||||
}
|
||||
}
|
||||
MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if mi.meta_item_or_bool().is_none() {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: mi.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(mi.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The unwraps below may look dangerous, but we've already asserted
|
||||
// that they won't fail with the loop above.
|
||||
match cfg.name() {
|
||||
Some(sym::any) => mis
|
||||
.iter()
|
||||
// We don't use any() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::all) => mis
|
||||
.iter()
|
||||
// We don't use all() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::not) => {
|
||||
let [mi] = mis.as_slice() else {
|
||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||
return false;
|
||||
};
|
||||
|
||||
!eval_condition(mi, sess, features, eval)
|
||||
}
|
||||
Some(sym::target) => {
|
||||
if let Some(features) = features
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::cfg_target_compact,
|
||||
cfg.span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
mis.iter().fold(true, |res, mi| {
|
||||
let Some(mut mi) = mi.meta_item().cloned() else {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: mi.span(),
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
if let [seg, ..] = &mut mi.path.segments[..] {
|
||||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
||||
}
|
||||
|
||||
res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: cfg.span,
|
||||
predicate: pprust::path_to_string(&cfg.path),
|
||||
});
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..)
|
||||
if cfg.path.segments.len() != 1
|
||||
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
|
||||
{
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||
true
|
||||
}
|
||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::CfgString,
|
||||
is_bytestr: lit.kind.is_bytestr(),
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
true
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..) => {
|
||||
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
||||
eval(Condition {
|
||||
name: ident.name,
|
||||
name_span: ident.span,
|
||||
value: cfg.value_str(),
|
||||
value_span: cfg.name_value_literal_span(),
|
||||
span: cfg.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ mod prelude;
|
|||
pub(crate) mod allow_unstable;
|
||||
pub(crate) mod body;
|
||||
pub(crate) mod cfg;
|
||||
pub(crate) mod cfg_old;
|
||||
pub(crate) mod cfg_select;
|
||||
pub(crate) mod codegen_attrs;
|
||||
pub(crate) mod confusables;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_hir::{
|
|||
|
||||
use super::prelude::*;
|
||||
use super::util::parse_version;
|
||||
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
|
||||
use crate::session_diagnostics::{self};
|
||||
|
||||
macro_rules! reject_outside_std {
|
||||
($cx: ident) => {
|
||||
|
|
@ -302,12 +302,7 @@ pub(crate) fn parse_stability<S: Stage>(
|
|||
for param in list.mixed() {
|
||||
let param_span = param.span();
|
||||
let Some(param) = param.meta_item() else {
|
||||
cx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: param_span,
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: cx.sess().source_map().start_point(param_span),
|
||||
});
|
||||
cx.unexpected_literal(param.span());
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
@ -382,12 +377,7 @@ pub(crate) fn parse_unstability<S: Stage>(
|
|||
|
||||
for param in list.mixed() {
|
||||
let Some(param) = param.meta_item() else {
|
||||
cx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: param.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: cx.sess().source_map().start_point(param.span()),
|
||||
});
|
||||
cx.unexpected_literal(param.span());
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,6 @@ pub mod validate_attr;
|
|||
pub use attributes::cfg::{
|
||||
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
|
||||
};
|
||||
pub use attributes::cfg_old::*;
|
||||
pub use attributes::cfg_select::*;
|
||||
pub use attributes::util::{is_builtin_attr, parse_version};
|
||||
pub use context::{Early, Late, OmitDoc, ShouldEmit};
|
||||
|
|
|
|||
|
|
@ -12,19 +12,6 @@ use rustc_span::{Span, Symbol};
|
|||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
pub(crate) enum UnsupportedLiteralReason {
|
||||
Generic,
|
||||
CfgString,
|
||||
CfgBoolean,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)]
|
||||
pub(crate) struct ExpectedOneCfgPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_predicate, code = E0537)]
|
||||
pub(crate) struct InvalidPredicate {
|
||||
|
|
@ -230,46 +217,6 @@ pub(crate) struct InvalidReprHintNoValue {
|
|||
pub name: Symbol,
|
||||
}
|
||||
|
||||
/// Error code: E0565
|
||||
// FIXME(jdonszelmann): slowly phased out
|
||||
pub(crate) struct UnsupportedLiteral {
|
||||
pub span: Span,
|
||||
pub reason: UnsupportedLiteralReason,
|
||||
pub is_bytestr: bool,
|
||||
pub start_point_span: Span,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let mut diag = Diag::new(
|
||||
dcx,
|
||||
level,
|
||||
match self.reason {
|
||||
UnsupportedLiteralReason::Generic => {
|
||||
fluent::attr_parsing_unsupported_literal_generic
|
||||
}
|
||||
UnsupportedLiteralReason::CfgString => {
|
||||
fluent::attr_parsing_unsupported_literal_cfg_string
|
||||
}
|
||||
UnsupportedLiteralReason::CfgBoolean => {
|
||||
fluent::attr_parsing_unsupported_literal_cfg_boolean
|
||||
}
|
||||
},
|
||||
);
|
||||
diag.span(self.span);
|
||||
diag.code(E0565);
|
||||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
self.start_point_span,
|
||||
fluent::attr_parsing_unsupported_literal_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)]
|
||||
pub(crate) struct InvalidReprAlignNeedArg {
|
||||
|
|
@ -375,13 +322,6 @@ pub(crate) struct RustcAllowedUnstablePairing {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_cfg_predicate_identifier)]
|
||||
pub(crate) struct CfgPredicateIdentifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_deprecated_item_suggestion)]
|
||||
pub(crate) struct DeprecatedItemSuggestion {
|
||||
|
|
|
|||
|
|
@ -561,11 +561,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
VarDebugInfoContents::Place(ref p) => p == place,
|
||||
_ => false,
|
||||
});
|
||||
let arg_name = if let Some(var_info) = var_info {
|
||||
var_info.name
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let Some(var_info) = var_info else { return };
|
||||
let arg_name = var_info.name;
|
||||
struct MatchArgFinder {
|
||||
expr_span: Span,
|
||||
match_arg_span: Option<Span>,
|
||||
|
|
|
|||
|
|
@ -850,16 +850,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
// will only ever have one item at any given time, but by using a vector, we can pop from
|
||||
// it which simplifies the termination logic.
|
||||
let mut queue = vec![location];
|
||||
let mut target =
|
||||
if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt else {
|
||||
return false;
|
||||
};
|
||||
let Some(mut target) = place.as_local() else { return false };
|
||||
|
||||
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
|
||||
while let Some(current_location) = queue.pop() {
|
||||
|
|
|
|||
|
|
@ -1124,16 +1124,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
use self::UseSpans::*;
|
||||
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
|
||||
|
||||
let target = match self.body[location.block].statements.get(location.statement_index) {
|
||||
Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
return OtherUse(use_span);
|
||||
}
|
||||
}
|
||||
_ => return OtherUse(use_span),
|
||||
let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) =
|
||||
self.body[location.block].statements.get(location.statement_index)
|
||||
else {
|
||||
return OtherUse(use_span);
|
||||
};
|
||||
let Some(target) = place.as_local() else { return OtherUse(use_span) };
|
||||
|
||||
if self.body.local_kind(target) != LocalKind::Temp {
|
||||
// operands are always temporaries.
|
||||
|
|
|
|||
|
|
@ -142,12 +142,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
} else {
|
||||
item_msg = access_place_desc;
|
||||
let local_info = self.body.local_decls[local].local_info();
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||
reason = format!(", as `{static_name}` is an immutable static item");
|
||||
} else {
|
||||
let LocalInfo::StaticRef { def_id, .. } = *local_info else {
|
||||
bug!("is_ref_to_static return true, but not ref to static?");
|
||||
}
|
||||
};
|
||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||
reason = format!(", as `{static_name}` is an immutable static item");
|
||||
}
|
||||
}
|
||||
PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => {
|
||||
|
|
|
|||
|
|
@ -847,11 +847,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
|
||||
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.scope);
|
||||
|
||||
let param = if let Some(param) =
|
||||
let Some(param) =
|
||||
find_param_with_region(self.infcx.tcx, self.mir_def_id(), f, outlived_f)
|
||||
{
|
||||
param
|
||||
} else {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -930,37 +928,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
|
||||
let (fn_did, args) = match func_ty.kind() {
|
||||
ty::FnDef(fn_did, args) => (fn_did, args),
|
||||
_ => return,
|
||||
};
|
||||
debug!(?fn_did, ?args);
|
||||
let ConstraintCategory::CallArgument(Some(func_ty)) = category else { return };
|
||||
let ty::FnDef(fn_did, args) = func_ty.kind() else { return };
|
||||
debug!(?fn_did, ?args);
|
||||
|
||||
// Only suggest this on function calls, not closures
|
||||
let ty = tcx.type_of(fn_did).instantiate_identity();
|
||||
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
|
||||
if let ty::Closure(_, _) = ty.kind() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(Some(instance)) = ty::Instance::try_resolve(
|
||||
tcx,
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
*fn_did,
|
||||
self.infcx.resolve_vars_if_possible(args),
|
||||
) {
|
||||
instance
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only suggest this on function calls, not closures
|
||||
let ty = tcx.type_of(fn_did).instantiate_identity();
|
||||
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
|
||||
if let ty::Closure(_, _) = ty.kind() {
|
||||
return;
|
||||
}
|
||||
let Ok(Some(instance)) = ty::Instance::try_resolve(
|
||||
tcx,
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
*fn_did,
|
||||
self.infcx.resolve_vars_if_possible(args),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let param = match find_param_with_region(tcx, self.mir_def_id(), f, o) {
|
||||
Some(param) => param,
|
||||
None => return,
|
||||
let Some(param) = find_param_with_region(tcx, self.mir_def_id(), f, o) else {
|
||||
return;
|
||||
};
|
||||
debug!(?param);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(file_buffered)]
|
||||
|
|
|
|||
|
|
@ -67,12 +67,11 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
|
|||
match context {
|
||||
PlaceContext::NonMutatingUse(_)
|
||||
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
|
||||
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
|
||||
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
|
||||
_ => {
|
||||
// There's no path access to emit.
|
||||
return;
|
||||
}
|
||||
let (LookupResult::Exact(path) | LookupResult::Parent(Some(path))) =
|
||||
self.move_data.rev_lookup.find(place.as_ref())
|
||||
else {
|
||||
// There's no path access to emit.
|
||||
return;
|
||||
};
|
||||
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
|
||||
self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));
|
||||
|
|
|
|||
|
|
@ -130,11 +130,9 @@ impl UnwindContext {
|
|||
return;
|
||||
}
|
||||
|
||||
let unwind_info = if let Some(unwind_info) =
|
||||
let Some(unwind_info) =
|
||||
context.compiled_code().unwrap().create_unwind_info(module.isa()).unwrap()
|
||||
{
|
||||
unwind_info
|
||||
} else {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,7 @@ pub(crate) fn maybe_known_branch_taken(
|
|||
arg: Value,
|
||||
test_zero: bool,
|
||||
) -> Option<bool> {
|
||||
let arg_inst = if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
|
||||
arg_inst
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) else { return None };
|
||||
|
||||
match bcx.func.dfg.insts[arg_inst] {
|
||||
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
|
||||
|
|
|
|||
|
|
@ -460,9 +460,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
}
|
||||
sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
|
||||
sym::rotate_left | sym::rotate_right => {
|
||||
// TODO(antoyo): implement using algorithm from:
|
||||
// Using optimized branchless algorithm from:
|
||||
// https://blog.regehr.org/archives/1063
|
||||
// for other platforms.
|
||||
// This implementation uses the pattern (x<<n) | (x>>(-n&(width-1)))
|
||||
// which generates efficient code for other platforms.
|
||||
let is_left = name == sym::rotate_left;
|
||||
let val = args[0].immediate();
|
||||
let raw_shift = args[1].immediate();
|
||||
|
|
|
|||
|
|
@ -774,24 +774,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
return Err(());
|
||||
}};
|
||||
}
|
||||
let (elem_ty_str, elem_ty, cast_type) = if let ty::Float(ref f) = *in_elem.kind() {
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
match f.bit_width() {
|
||||
16 => ("", elem_ty, Some(bx.cx.double_type)),
|
||||
32 => ("f", elem_ty, None),
|
||||
64 => ("", elem_ty, None),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::FloatingPointVector {
|
||||
span,
|
||||
name,
|
||||
f_ty: *f,
|
||||
in_ty
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let ty::Float(ref f) = *in_elem.kind() else {
|
||||
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
|
||||
};
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
let (elem_ty_str, elem_ty, cast_type) = match f.bit_width() {
|
||||
16 => ("", elem_ty, Some(bx.cx.double_type)),
|
||||
32 => ("f", elem_ty, None),
|
||||
64 => ("", elem_ty, None),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::FloatingPointVector {
|
||||
span,
|
||||
name,
|
||||
f_ty: *f,
|
||||
in_ty
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
|
||||
|
||||
|
|
|
|||
|
|
@ -1756,11 +1756,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}};
|
||||
}
|
||||
|
||||
let elem_ty = if let ty::Float(f) = in_elem.kind() {
|
||||
bx.cx.type_float_from_ty(*f)
|
||||
} else {
|
||||
let ty::Float(f) = in_elem.kind() else {
|
||||
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
|
||||
};
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
|
||||
let vec_ty = bx.type_vector(elem_ty, in_len);
|
||||
|
||||
|
|
|
|||
|
|
@ -721,11 +721,10 @@ pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
|
|||
};
|
||||
|
||||
// First read the ret symbol from the attribute
|
||||
let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity {
|
||||
p1.segments.first().unwrap().ident
|
||||
} else {
|
||||
let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity else {
|
||||
span_bug!(attr.span(), "rustc_autodiff attribute must contain the return activity");
|
||||
};
|
||||
let ret_symbol = p1.segments.first().unwrap().ident;
|
||||
|
||||
// Then parse it into an actual DiffActivity
|
||||
let Ok(ret_activity) = DiffActivity::from_str(ret_symbol.as_str()) else {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(array_try_map)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ impl_dyn_send!(
|
|||
[std::sync::Mutex<T> where T: ?Sized+ DynSend]
|
||||
[std::sync::mpsc::Sender<T> where T: DynSend]
|
||||
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::Weak<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
|
||||
[std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
|
||||
[std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
|
||||
|
|
@ -157,6 +158,7 @@ impl_dyn_sync!(
|
|||
[std::sync::OnceLock<T> where T: DynSend + DynSync]
|
||||
[std::sync::Mutex<T> where T: ?Sized + DynSend]
|
||||
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::Weak<T> where T: ?Sized + DynSync + DynSend]
|
||||
[std::sync::LazyLock<T, F> where T: DynSend + DynSync, F: DynSend]
|
||||
[std::collections::HashSet<K, S> where K: DynSync, S: DynSync]
|
||||
[std::collections::HashMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
The `not` cfg-predicate was malformed.
|
||||
|
||||
Erroneous code example (using `cargo doc`):
|
||||
|
|
|
|||
|
|
@ -788,11 +788,10 @@ pub fn compile_declarative_macro(
|
|||
let lhs_span = lhs_tt.span();
|
||||
// Convert the lhs into `MatcherLoc` form, which is better for doing the
|
||||
// actual matching.
|
||||
let lhs = if let mbe::TokenTree::Delimited(.., delimited) = lhs_tt {
|
||||
mbe::macro_parser::compute_locs(&delimited.tts)
|
||||
} else {
|
||||
let mbe::TokenTree::Delimited(.., delimited) = lhs_tt else {
|
||||
return dummy_syn_ext(guar.unwrap());
|
||||
};
|
||||
let lhs = mbe::macro_parser::compute_locs(&delimited.tts);
|
||||
if let Some(args) = args {
|
||||
let args_span = args.span();
|
||||
let mbe::TokenTree::Delimited(.., delimited) = args else {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(const_default)]
|
||||
|
|
|
|||
|
|
@ -1551,15 +1551,15 @@ fn const_param_default<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) => ct,
|
||||
_ => span_bug!(
|
||||
let hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
|
||||
..
|
||||
}) = tcx.hir_node_by_def_id(def_id)
|
||||
else {
|
||||
span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
)
|
||||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
|
|
|
|||
|
|
@ -188,29 +188,26 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
|
|||
for (param, var) in std::iter::zip(&generics.own_params, gat_vars) {
|
||||
let existing = match var.kind() {
|
||||
ty::GenericArgKind::Lifetime(re) => {
|
||||
if let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
|
||||
let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
|
||||
re.kind()
|
||||
{
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
} else {
|
||||
else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => {
|
||||
if let ty::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) = *ty.kind() {
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
} else {
|
||||
let ty::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) = *ty.kind() else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
}
|
||||
ty::GenericArgKind::Const(ct) => {
|
||||
if let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
|
||||
let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
|
||||
ct.kind()
|
||||
{
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
} else {
|
||||
else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
mapping.insert(bv.var, tcx.mk_param_from_def(param))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -763,9 +763,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
&self,
|
||||
err: &mut Diag<'_, impl EmissionGuarantee>,
|
||||
) {
|
||||
let trait_ = match self.tcx.trait_of_assoc(self.def_id) {
|
||||
Some(def_id) => def_id,
|
||||
None => return,
|
||||
let Some(trait_) = self.tcx.trait_of_assoc(self.def_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Skip suggestion when the associated function is itself generic, it is unclear
|
||||
|
|
@ -1077,15 +1076,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
|
||||
/// Builds the `type defined here` message.
|
||||
fn show_definition(&self, err: &mut Diag<'_, impl EmissionGuarantee>) {
|
||||
let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
|
||||
if self.tcx.sess.source_map().is_span_accessible(def_span) {
|
||||
def_span.into()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let Some(def_span) = self.tcx.def_ident_span(self.def_id) else { return };
|
||||
if !self.tcx.sess.source_map().is_span_accessible(def_span) {
|
||||
return;
|
||||
};
|
||||
let mut spans: MultiSpan = def_span.into();
|
||||
|
||||
let msg = {
|
||||
let def_kind = self.tcx.def_descr(self.def_id);
|
||||
|
|
|
|||
|
|
@ -1749,10 +1749,8 @@ fn generics_args_err_extend<'a>(
|
|||
GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
|
||||
let ty = tcx.at(span).type_of(def_id).instantiate_identity();
|
||||
let span_of_impl = tcx.span_of_impl(def_id);
|
||||
let def_id = match *ty.kind() {
|
||||
ty::Adt(self_def, _) => self_def.did(),
|
||||
_ => return,
|
||||
};
|
||||
let ty::Adt(self_def, _) = *ty.kind() else { return };
|
||||
let def_id = self_def.did();
|
||||
|
||||
let type_name = tcx.item_name(def_id);
|
||||
let span_of_ty = tcx.def_ident_span(def_id);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ This API is completely unstable and subject to change.
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -458,15 +458,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
// Actually need to unwrap one more layer of HIR to get to
|
||||
// the _real_ closure...
|
||||
if let hir::Node::Expr(&hir::Expr {
|
||||
let hir::Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
|
||||
..
|
||||
}) = self.tcx.parent_hir_node(parent_hir_id)
|
||||
{
|
||||
fn_decl_span
|
||||
} else {
|
||||
else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
fn_decl_span
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -415,11 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
});
|
||||
Some(self.resolve_vars_if_possible(possible_rcvr_ty))
|
||||
});
|
||||
if let Some(rcvr_ty) = possible_rcvr_ty {
|
||||
rcvr_ty
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
let Some(rcvr_ty) = possible_rcvr_ty else { return false };
|
||||
rcvr_ty
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3180,6 +3180,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_label(within_macro_span, "due to this macro variable");
|
||||
}
|
||||
|
||||
// Check if there is an associated function with the same name.
|
||||
if let Some(def_id) = base_ty.peel_refs().ty_adt_def().map(|d| d.did()) {
|
||||
for impl_def_id in self.tcx.inherent_impls(def_id) {
|
||||
for item in self.tcx.associated_items(impl_def_id).in_definition_order() {
|
||||
if let ExprKind::Field(base_expr, _) = expr.kind
|
||||
&& item.name() == field.name
|
||||
&& matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
|
||||
{
|
||||
err.span_label(field.span, "this is an associated function, not a method");
|
||||
err.note("found the following associated function; to be used as method, it must have a `self` parameter");
|
||||
let impl_ty = self.tcx.type_of(impl_def_id).instantiate_identity();
|
||||
err.span_note(
|
||||
self.tcx.def_span(item.def_id),
|
||||
format!("the candidate is defined in an impl for the type `{impl_ty}`"),
|
||||
);
|
||||
|
||||
let ty_str = match base_ty.peel_refs().kind() {
|
||||
ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args),
|
||||
_ => base_ty.peel_refs().to_string(),
|
||||
};
|
||||
err.multipart_suggestion(
|
||||
"use associated function syntax instead",
|
||||
vec![
|
||||
(base_expr.span, ty_str),
|
||||
(base_expr.span.between(field.span), "::".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try to add a suggestion in case the field is a nested field of a field of the Adt
|
||||
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
|
||||
let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind()
|
||||
|
|
|
|||
|
|
@ -1561,19 +1561,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
base_place: PlaceWithHirId<'tcx>,
|
||||
) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
|
||||
let base_curr_ty = base_place.place.ty();
|
||||
let deref_ty = match self
|
||||
let Some(deref_ty) = self
|
||||
.cx
|
||||
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
|
||||
.builtin_deref(true)
|
||||
{
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||
return Err(self.cx.report_bug(
|
||||
self.cx.tcx().hir_span(node),
|
||||
"explicit deref of non-derefable type",
|
||||
));
|
||||
}
|
||||
else {
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||
return Err(self
|
||||
.cx
|
||||
.report_bug(self.cx.tcx().hir_span(node), "explicit deref of non-derefable type"));
|
||||
};
|
||||
let mut projections = base_place.place.projections;
|
||||
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
|
||||
|
|
|
|||
|
|
@ -48,33 +48,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let uninstantiated_pred = match flavor {
|
||||
ClauseFlavor::Where => {
|
||||
ClauseFlavor::Where
|
||||
if let Some(pred) = self
|
||||
.tcx
|
||||
.predicates_of(def_id)
|
||||
.instantiate_identity(self.tcx)
|
||||
.predicates
|
||||
.into_iter()
|
||||
.nth(idx)
|
||||
{
|
||||
pred
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
.nth(idx) =>
|
||||
{
|
||||
pred
|
||||
}
|
||||
ClauseFlavor::Const => {
|
||||
ClauseFlavor::Const
|
||||
if let Some((pred, _)) = self
|
||||
.tcx
|
||||
.const_conditions(def_id)
|
||||
.instantiate_identity(self.tcx)
|
||||
.into_iter()
|
||||
.nth(idx)
|
||||
{
|
||||
pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
.nth(idx) =>
|
||||
{
|
||||
pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
|
|
|
|||
|
|
@ -1467,11 +1467,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => None,
|
||||
}
|
||||
});
|
||||
if let Some(new_def_id) = new_def_id {
|
||||
def_id = new_def_id;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let Some(new_def_id) = new_def_id else { return };
|
||||
def_id = new_def_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1795,7 +1795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(ty),
|
||||
hir::Path { segments: [segment], .. },
|
||||
))
|
||||
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
|
||||
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment))
|
||||
if let Some(self_ty) = self.typeck_results.borrow().node_type_opt(ty.hir_id)
|
||||
&& let Ok(pick) = self.probe_for_name(
|
||||
Mode::Path,
|
||||
|
|
@ -1805,12 +1805,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self_ty,
|
||||
expr.hir_id,
|
||||
ProbeScope::TraitsInScope,
|
||||
)
|
||||
{
|
||||
(pick.item, segment)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
) =>
|
||||
{
|
||||
(pick.item, segment)
|
||||
}
|
||||
hir::ExprKind::Path(QPath::Resolved(
|
||||
None,
|
||||
|
|
@ -1821,16 +1818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if old_item_name != segment.ident.name {
|
||||
return false;
|
||||
}
|
||||
if let Some(item) = self
|
||||
let Some(item) = self
|
||||
.tcx
|
||||
.associated_items(self.tcx.parent(old_def_id))
|
||||
.filter_by_name_unhygienic(capitalized_name)
|
||||
.next()
|
||||
{
|
||||
(*item, segment)
|
||||
} else {
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
(*item, segment)
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -121,13 +121,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
len,
|
||||
)
|
||||
};
|
||||
if let Some(len) = len.try_to_target_usize(self.tcx()) {
|
||||
(len, ty)
|
||||
} else {
|
||||
let Some(len) = len.try_to_target_usize(self.tcx()) else {
|
||||
return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
|
||||
field.did, len,
|
||||
));
|
||||
}
|
||||
};
|
||||
(len, ty)
|
||||
}
|
||||
_ => (fields.len() as u64, elem_ty),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// tidy-alphabetical-start
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -2511,7 +2511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
applicability = Applicability::HasPlaceholders;
|
||||
"(...)".to_owned()
|
||||
};
|
||||
err.span_suggestion(
|
||||
err.span_suggestion_verbose(
|
||||
sugg_span,
|
||||
"use associated function syntax instead",
|
||||
format!("{ty_str}::{item_name}{args}"),
|
||||
|
|
@ -3543,10 +3543,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: Span,
|
||||
return_type: Option<Ty<'tcx>>,
|
||||
) {
|
||||
let output_ty = match self.err_ctxt().get_impl_future_output_ty(ty) {
|
||||
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
|
||||
_ => return,
|
||||
};
|
||||
let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else { return };
|
||||
let output_ty = self.resolve_vars_if_possible(output_ty);
|
||||
let method_exists =
|
||||
self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
|
||||
debug!("suggest_await_before_method: is_method_exist={}", method_exists);
|
||||
|
|
|
|||
|
|
@ -1072,11 +1072,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
|||
cx: &LateContext<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
|
||||
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
||||
cx.qpath_res(qpath, expr.hir_id)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let hir::ExprKind::Path(ref qpath) = expr.kind else { return None };
|
||||
let def = cx.qpath_res(qpath, expr.hir_id);
|
||||
if let Res::Def(DefKind::Fn, did) = def {
|
||||
if !def_id_is_transmute(cx, did) {
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -120,10 +120,8 @@ impl Expr2024 {
|
|||
|
||||
fn check_ident_token(&mut self, cx: &crate::EarlyContext<'_>, token: &Token) {
|
||||
debug!("check_ident_token: {:?}", token);
|
||||
let (sym, edition) = match token.kind {
|
||||
TokenKind::Ident(sym, _) => (sym, Edition::Edition2024),
|
||||
_ => return,
|
||||
};
|
||||
let TokenKind::Ident(sym, _) = token.kind else { return };
|
||||
let edition = Edition::Edition2024;
|
||||
|
||||
debug!("token.span.edition(): {:?}", token.span.edition());
|
||||
if token.span.edition() >= edition {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ declare_lint_pass! {
|
|||
ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
INCOMPLETE_INCLUDE,
|
||||
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
||||
INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES,
|
||||
INLINE_NO_SANITIZE,
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
|
|
|||
|
|
@ -706,12 +706,9 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
|
|||
| Bound(_, _)
|
||||
| Placeholder(_)
|
||||
| Error(_) => {
|
||||
if let Some(placeholder) = self.placeholder {
|
||||
// We replace these with infer (which is passed in from an infcx).
|
||||
placeholder
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
let Some(placeholder) = self.placeholder else { return Err(()) };
|
||||
// We replace these with infer (which is passed in from an infcx).
|
||||
placeholder
|
||||
}
|
||||
|
||||
Alias(Opaque, AliasTy { def_id, .. }) => {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ pub use generic_args::{GenericArgKind, TermKind, *};
|
|||
pub use generics::*;
|
||||
pub use intrinsic::IntrinsicDef;
|
||||
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
|
||||
use rustc_ast::AttrVec;
|
||||
use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree};
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
pub use rustc_ast_ir::{Movability, Mutability, try_visit};
|
||||
|
|
@ -221,13 +222,24 @@ pub struct ResolverAstLowering {
|
|||
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DelegationFnSigAttrs: u8 {
|
||||
const TARGET_FEATURE = 1 << 0;
|
||||
const MUST_USE = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub const DELEGATION_INHERIT_ATTRS_START: DelegationFnSigAttrs = DelegationFnSigAttrs::MUST_USE;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DelegationFnSig {
|
||||
pub header: ast::FnHeader,
|
||||
pub param_count: usize,
|
||||
pub has_self: bool,
|
||||
pub c_variadic: bool,
|
||||
pub target_feature: bool,
|
||||
pub attrs_flags: DelegationFnSigAttrs,
|
||||
pub to_inherit_attrs: AttrVec,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, HashStable)]
|
||||
|
|
@ -2395,9 +2407,7 @@ fn typetree_from_ty_impl_inner<'tcx>(
|
|||
}
|
||||
|
||||
if ty.is_ref() || ty.is_raw_ptr() || ty.is_box() {
|
||||
let inner_ty = if let Some(inner) = ty.builtin_deref(true) {
|
||||
inner
|
||||
} else {
|
||||
let Some(inner_ty) = ty.builtin_deref(true) else {
|
||||
return TypeTree::new();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1528,18 +1528,13 @@ impl<'tcx> Ty<'tcx> {
|
|||
let mut cor_ty = self;
|
||||
let mut ty = cor_ty;
|
||||
loop {
|
||||
if let ty::Coroutine(def_id, args) = ty.kind() {
|
||||
cor_ty = ty;
|
||||
f(ty);
|
||||
if tcx.is_async_drop_in_place_coroutine(*def_id) {
|
||||
ty = args.first().unwrap().expect_ty();
|
||||
continue;
|
||||
} else {
|
||||
return cor_ty;
|
||||
}
|
||||
} else {
|
||||
let ty::Coroutine(def_id, args) = ty.kind() else { return cor_ty };
|
||||
cor_ty = ty;
|
||||
f(ty);
|
||||
if !tcx.is_async_drop_in_place_coroutine(*def_id) {
|
||||
return cor_ty;
|
||||
}
|
||||
ty = args.first().unwrap().expect_ty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,11 +100,8 @@ impl<'tcx> MovePath<'tcx> {
|
|||
move_paths: &IndexSlice<MovePathIndex, MovePath<'_>>,
|
||||
f: impl Fn(MovePathIndex) -> bool,
|
||||
) -> Option<MovePathIndex> {
|
||||
let mut todo = if let Some(child) = self.first_child {
|
||||
vec![child]
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let Some(child) = self.first_child else { return None };
|
||||
let mut todo = vec![child];
|
||||
|
||||
while let Some(mpi) = todo.pop() {
|
||||
if f(mpi) {
|
||||
|
|
@ -331,11 +328,10 @@ impl<'tcx> MovePathLookup<'tcx> {
|
|||
MoveSubPathResult::Stop => None,
|
||||
};
|
||||
|
||||
if let Some(&subpath) = subpath {
|
||||
result = subpath;
|
||||
} else {
|
||||
let Some(&subpath) = subpath else {
|
||||
return LookupResult::Parent(Some(result));
|
||||
}
|
||||
};
|
||||
result = subpath;
|
||||
}
|
||||
|
||||
LookupResult::Exact(result)
|
||||
|
|
|
|||
|
|
@ -721,11 +721,8 @@ impl<'tcx> Map<'tcx> {
|
|||
// Enum variant fields and enum discriminants alias each another.
|
||||
self.for_each_variant_sibling(index, sub, f);
|
||||
}
|
||||
if let Some(sub) = sub {
|
||||
index = sub
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let Some(sub) = sub else { return };
|
||||
index = sub;
|
||||
}
|
||||
self.for_each_value_inside(index, f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -590,31 +590,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
|
|||
let fields =
|
||||
fields.iter().map(|&f| self.eval_to_const(f)).collect::<Option<Vec<_>>>()?;
|
||||
let variant = if ty.ty.is_enum() { Some(variant) } else { None };
|
||||
if matches!(ty.backend_repr, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..))
|
||||
{
|
||||
let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
|
||||
let variant_dest = if let Some(variant) = variant {
|
||||
self.ecx.project_downcast(&dest, variant).discard_err()?
|
||||
} else {
|
||||
dest.clone()
|
||||
};
|
||||
for (field_index, op) in fields.into_iter().enumerate() {
|
||||
let field_dest = self
|
||||
.ecx
|
||||
.project_field(&variant_dest, FieldIdx::from_usize(field_index))
|
||||
.discard_err()?;
|
||||
self.ecx.copy_op(op, &field_dest).discard_err()?;
|
||||
}
|
||||
self.ecx
|
||||
.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest)
|
||||
.discard_err()?;
|
||||
self.ecx
|
||||
.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id())
|
||||
.discard_err()?;
|
||||
dest.into()
|
||||
} else {
|
||||
let (BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) = ty.backend_repr
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
|
||||
let variant_dest = if let Some(variant) = variant {
|
||||
self.ecx.project_downcast(&dest, variant).discard_err()?
|
||||
} else {
|
||||
dest.clone()
|
||||
};
|
||||
for (field_index, op) in fields.into_iter().enumerate() {
|
||||
let field_dest = self
|
||||
.ecx
|
||||
.project_field(&variant_dest, FieldIdx::from_usize(field_index))
|
||||
.discard_err()?;
|
||||
self.ecx.copy_op(op, &field_dest).discard_err()?;
|
||||
}
|
||||
self.ecx
|
||||
.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest)
|
||||
.discard_err()?;
|
||||
self.ecx
|
||||
.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id())
|
||||
.discard_err()?;
|
||||
dest.into()
|
||||
}
|
||||
Union(active_field, field) => {
|
||||
let field = self.eval_to_const(field)?;
|
||||
|
|
|
|||
|
|
@ -410,14 +410,8 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
// In theory, any zero-sized value could be borrowed
|
||||
// mutably without consequences. However, only &mut []
|
||||
// is allowed right now.
|
||||
if let ty::Array(_, len) = ty.kind() {
|
||||
match len.try_to_target_usize(self.tcx) {
|
||||
Some(0) => {}
|
||||
_ => return Err(Unpromotable),
|
||||
}
|
||||
} else {
|
||||
return Err(Unpromotable);
|
||||
}
|
||||
let ty::Array(_, len) = ty.kind() else { return Err(Unpromotable) };
|
||||
let Some(0) = len.try_to_target_usize(self.tcx) else { return Err(Unpromotable) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -445,17 +445,15 @@ where
|
|||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let cx = ecx.cx();
|
||||
let tupled_inputs_and_output =
|
||||
match structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
let Some(tupled_inputs_and_output) =
|
||||
structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
)? {
|
||||
Some(tupled_inputs_and_output) => tupled_inputs_and_output,
|
||||
None => {
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
}
|
||||
};
|
||||
)?
|
||||
else {
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
};
|
||||
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
|
||||
|
||||
// A built-in `Fn` impl only holds if the output is sized.
|
||||
|
|
|
|||
|
|
@ -360,17 +360,15 @@ where
|
|||
}
|
||||
|
||||
let cx = ecx.cx();
|
||||
let tupled_inputs_and_output =
|
||||
match structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
let Some(tupled_inputs_and_output) =
|
||||
structural_traits::extract_tupled_inputs_and_output_from_callable(
|
||||
cx,
|
||||
goal.predicate.self_ty(),
|
||||
goal_kind,
|
||||
)? {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
}
|
||||
};
|
||||
)?
|
||||
else {
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
};
|
||||
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
|
||||
|
||||
// A built-in `Fn` impl only holds if the output is sized.
|
||||
|
|
@ -1409,42 +1407,39 @@ where
|
|||
let where_bounds: Vec<_> = candidates
|
||||
.extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
|
||||
.collect();
|
||||
if let Some((response, info)) = self.try_merge_candidates(&where_bounds) {
|
||||
match info {
|
||||
// If there's an always applicable candidate, the result of all
|
||||
// other candidates does not matter. This means we can ignore
|
||||
// them when checking whether we've reached a fixpoint.
|
||||
//
|
||||
// We always prefer the first always applicable candidate, even if a
|
||||
// later candidate is also always applicable and would result in fewer
|
||||
// reruns. We could slightly improve this by e.g. searching for another
|
||||
// always applicable candidate which doesn't depend on any cycle heads.
|
||||
//
|
||||
// NOTE: This is optimization is observable in case there is an always
|
||||
// applicable global candidate and another non-global candidate which only
|
||||
// applies because of a provisional result. I can't even think of a test
|
||||
// case where this would occur and even then, this would not be unsound.
|
||||
// Supporting this makes the code more involved, so I am just going to
|
||||
// ignore this for now.
|
||||
MergeCandidateInfo::AlwaysApplicable(i) => {
|
||||
for (j, c) in where_bounds.into_iter().enumerate() {
|
||||
if i != j {
|
||||
self.ignore_candidate_head_usages(c.head_usages)
|
||||
}
|
||||
}
|
||||
// If a where-bound does not apply, we don't actually get a
|
||||
// candidate for it. We manually track the head usages
|
||||
// of all failed `ParamEnv` candidates instead.
|
||||
self.ignore_candidate_head_usages(
|
||||
failed_candidate_info.param_env_head_usages,
|
||||
);
|
||||
}
|
||||
MergeCandidateInfo::EqualResponse => {}
|
||||
}
|
||||
return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
|
||||
} else {
|
||||
let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
|
||||
return Ok((self.bail_with_ambiguity(&where_bounds), None));
|
||||
};
|
||||
match info {
|
||||
// If there's an always applicable candidate, the result of all
|
||||
// other candidates does not matter. This means we can ignore
|
||||
// them when checking whether we've reached a fixpoint.
|
||||
//
|
||||
// We always prefer the first always applicable candidate, even if a
|
||||
// later candidate is also always applicable and would result in fewer
|
||||
// reruns. We could slightly improve this by e.g. searching for another
|
||||
// always applicable candidate which doesn't depend on any cycle heads.
|
||||
//
|
||||
// NOTE: This is optimization is observable in case there is an always
|
||||
// applicable global candidate and another non-global candidate which only
|
||||
// applies because of a provisional result. I can't even think of a test
|
||||
// case where this would occur and even then, this would not be unsound.
|
||||
// Supporting this makes the code more involved, so I am just going to
|
||||
// ignore this for now.
|
||||
MergeCandidateInfo::AlwaysApplicable(i) => {
|
||||
for (j, c) in where_bounds.into_iter().enumerate() {
|
||||
if i != j {
|
||||
self.ignore_candidate_head_usages(c.head_usages)
|
||||
}
|
||||
}
|
||||
// If a where-bound does not apply, we don't actually get a
|
||||
// candidate for it. We manually track the head usages
|
||||
// of all failed `ParamEnv` candidates instead.
|
||||
self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
|
||||
}
|
||||
MergeCandidateInfo::EqualResponse => {}
|
||||
}
|
||||
return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
|
||||
}
|
||||
|
||||
// Next, prefer any alias bound (nested or otherwise).
|
||||
|
|
|
|||
|
|
@ -1363,7 +1363,10 @@ impl DepNodeColorMap {
|
|||
Ordering::Relaxed,
|
||||
) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(v) => Err(DepNodeIndex::from_u32(v)),
|
||||
Err(v) => Err({
|
||||
assert_ne!(v, COMPRESSED_RED, "tried to mark a red node as green");
|
||||
DepNodeIndex::from_u32(v)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1384,7 +1387,9 @@ impl DepNodeColorMap {
|
|||
|
||||
#[inline]
|
||||
pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) {
|
||||
self.values[index].store(COMPRESSED_RED, Ordering::Release)
|
||||
let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release);
|
||||
// Sanity check for duplicate nodes
|
||||
assert_eq!(value, COMPRESSED_UNKNOWN, "trying to encode a dep node twice");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -771,36 +771,39 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Skip ambiguity errors for extern flag bindings "overridden"
|
||||
// by extern item bindings.
|
||||
// FIXME: Remove with lang team approval.
|
||||
let issue_145575_hack = Some(binding) == extern_prelude_flag_binding
|
||||
&& extern_prelude_item_binding.is_some()
|
||||
&& extern_prelude_item_binding != Some(innermost_binding);
|
||||
if let Some(kind) = ambiguity_error_kind
|
||||
&& !issue_145575_hack
|
||||
{
|
||||
let misc = |f: Flags| {
|
||||
if f.contains(Flags::MISC_SUGGEST_CRATE) {
|
||||
AmbiguityErrorMisc::SuggestCrate
|
||||
} else if f.contains(Flags::MISC_SUGGEST_SELF) {
|
||||
AmbiguityErrorMisc::SuggestSelf
|
||||
} else if f.contains(Flags::MISC_FROM_PRELUDE) {
|
||||
AmbiguityErrorMisc::FromPrelude
|
||||
} else {
|
||||
AmbiguityErrorMisc::None
|
||||
}
|
||||
};
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
kind,
|
||||
ident: orig_ident,
|
||||
b1: innermost_binding,
|
||||
b2: binding,
|
||||
warning: false,
|
||||
misc1: misc(innermost_flags),
|
||||
misc2: misc(flags),
|
||||
});
|
||||
return true;
|
||||
if let Some(kind) = ambiguity_error_kind {
|
||||
// Skip ambiguity errors for extern flag bindings "overridden"
|
||||
// by extern item bindings.
|
||||
// FIXME: Remove with lang team approval.
|
||||
let issue_145575_hack = Some(binding) == extern_prelude_flag_binding
|
||||
&& extern_prelude_item_binding.is_some()
|
||||
&& extern_prelude_item_binding != Some(innermost_binding);
|
||||
|
||||
if issue_145575_hack {
|
||||
self.issue_145575_hack_applied = true;
|
||||
} else {
|
||||
let misc = |f: Flags| {
|
||||
if f.contains(Flags::MISC_SUGGEST_CRATE) {
|
||||
AmbiguityErrorMisc::SuggestCrate
|
||||
} else if f.contains(Flags::MISC_SUGGEST_SELF) {
|
||||
AmbiguityErrorMisc::SuggestSelf
|
||||
} else if f.contains(Flags::MISC_FROM_PRELUDE) {
|
||||
AmbiguityErrorMisc::FromPrelude
|
||||
} else {
|
||||
AmbiguityErrorMisc::None
|
||||
}
|
||||
};
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
kind,
|
||||
ident: orig_ident,
|
||||
b1: innermost_binding,
|
||||
b2: binding,
|
||||
warning: false,
|
||||
misc1: misc(innermost_flags),
|
||||
misc2: misc(flags),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
return;
|
||||
}
|
||||
if let Some(initial_res) = initial_res {
|
||||
if res != initial_res {
|
||||
if res != initial_res && !this.issue_145575_hack_applied {
|
||||
span_bug!(import.span, "inconsistent resolution for an import");
|
||||
}
|
||||
} else if this.privacy_errors.is_empty() {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
|
|||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
|
||||
use rustc_middle::middle::resolve_bound_vars::Set1;
|
||||
use rustc_middle::ty::{AssocTag, DelegationFnSig, Visibility};
|
||||
use rustc_middle::ty::{
|
||||
AssocTag, DELEGATION_INHERIT_ATTRS_START, DelegationFnSig, DelegationFnSigAttrs, Visibility,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::{CrateType, ResolveDocLinks};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -5297,13 +5299,37 @@ impl ItemInfoCollector<'_, '_, '_> {
|
|||
id: NodeId,
|
||||
attrs: &[Attribute],
|
||||
) {
|
||||
static NAMES_TO_FLAGS: &[(Symbol, DelegationFnSigAttrs)] = &[
|
||||
(sym::target_feature, DelegationFnSigAttrs::TARGET_FEATURE),
|
||||
(sym::must_use, DelegationFnSigAttrs::MUST_USE),
|
||||
];
|
||||
|
||||
let mut to_inherit_attrs = AttrVec::new();
|
||||
let mut attrs_flags = DelegationFnSigAttrs::empty();
|
||||
|
||||
'attrs_loop: for attr in attrs {
|
||||
for &(name, flag) in NAMES_TO_FLAGS {
|
||||
if attr.has_name(name) {
|
||||
attrs_flags.set(flag, true);
|
||||
|
||||
if flag.bits() >= DELEGATION_INHERIT_ATTRS_START.bits() {
|
||||
to_inherit_attrs.push(attr.clone());
|
||||
}
|
||||
|
||||
continue 'attrs_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sig = DelegationFnSig {
|
||||
header,
|
||||
param_count: decl.inputs.len(),
|
||||
has_self: decl.has_self(),
|
||||
c_variadic: decl.c_variadic(),
|
||||
target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
|
||||
attrs_flags,
|
||||
to_inherit_attrs,
|
||||
};
|
||||
|
||||
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1537,86 +1537,80 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
/// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
|
||||
fn restrict_assoc_type_in_where_clause(&self, span: Span, err: &mut Diag<'_>) -> bool {
|
||||
// Detect that we are actually in a `where` predicate.
|
||||
let (bounded_ty, bounds, where_span) = if let Some(ast::WherePredicate {
|
||||
let Some(ast::WherePredicate {
|
||||
kind:
|
||||
ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
|
||||
bounded_ty,
|
||||
bound_generic_params,
|
||||
bounds,
|
||||
}),
|
||||
span,
|
||||
span: where_span,
|
||||
..
|
||||
}) = self.diag_metadata.current_where_predicate
|
||||
{
|
||||
if !bound_generic_params.is_empty() {
|
||||
return false;
|
||||
}
|
||||
(bounded_ty, bounds, span)
|
||||
} else {
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if !bound_generic_params.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirm that the target is an associated type.
|
||||
let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
|
||||
// use this to verify that ident is a type param.
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
|
||||
return false;
|
||||
};
|
||||
if !matches!(
|
||||
partial_res.full_res(),
|
||||
Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
(&qself.ty, qself.position, path)
|
||||
} else {
|
||||
let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind else { return false };
|
||||
// use this to verify that ident is a type param.
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else { return false };
|
||||
if !matches!(
|
||||
partial_res.full_res(),
|
||||
Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let peeled_ty = qself.ty.peel_refs();
|
||||
let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind else { return false };
|
||||
// Confirm that the `SelfTy` is a type parameter.
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let peeled_ty = ty.peel_refs();
|
||||
if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
|
||||
// Confirm that the `SelfTy` is a type parameter.
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
|
||||
if !matches!(
|
||||
partial_res.full_res(),
|
||||
Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
let ([ast::PathSegment { args: None, .. }], [ast::GenericBound::Trait(poly_trait_ref)]) =
|
||||
(&type_param_path.segments[..], &bounds[..])
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let [ast::PathSegment { ident, args: None, id }] =
|
||||
&poly_trait_ref.trait_ref.path.segments[..]
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if poly_trait_ref.modifiers != ast::TraitBoundModifiers::NONE {
|
||||
return false;
|
||||
}
|
||||
if ident.span == span {
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&id) else {
|
||||
return false;
|
||||
};
|
||||
if !matches!(
|
||||
partial_res.full_res(),
|
||||
Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
|
||||
) {
|
||||
if !matches!(partial_res.full_res(), Some(hir::def::Res::Def(..))) {
|
||||
return false;
|
||||
}
|
||||
if let (
|
||||
[ast::PathSegment { args: None, .. }],
|
||||
[ast::GenericBound::Trait(poly_trait_ref)],
|
||||
) = (&type_param_path.segments[..], &bounds[..])
|
||||
&& let [ast::PathSegment { ident, args: None, id }] =
|
||||
&poly_trait_ref.trait_ref.path.segments[..]
|
||||
&& poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE
|
||||
{
|
||||
if ident.span == span {
|
||||
let Some(partial_res) = self.r.partial_res_map.get(&id) else {
|
||||
return false;
|
||||
};
|
||||
if !matches!(partial_res.full_res(), Some(hir::def::Res::Def(..))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(new_where_bound_predicate) =
|
||||
mk_where_bound_predicate(path, poly_trait_ref, ty)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
*where_span,
|
||||
format!("constrain the associated type to `{ident}`"),
|
||||
where_bound_predicate_to_string(&new_where_bound_predicate),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
let Some(new_where_bound_predicate) =
|
||||
mk_where_bound_predicate(path, poly_trait_ref, &qself.ty)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
*where_span,
|
||||
format!("constrain the associated type to `{ident}`"),
|
||||
where_bound_predicate_to_string(&new_where_bound_predicate),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
false
|
||||
true
|
||||
}
|
||||
|
||||
/// Check if the source is call expression and the first argument is `self`. If true,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
|
@ -1187,6 +1188,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
privacy_errors: Vec<PrivacyError<'ra>> = Vec::new(),
|
||||
/// Ambiguity errors are delayed for deduplication.
|
||||
ambiguity_errors: Vec<AmbiguityError<'ra>> = Vec::new(),
|
||||
issue_145575_hack_applied: bool = false,
|
||||
/// `use` injections are delayed for better placement and deduplication.
|
||||
use_injections: Vec<UseError<'tcx>> = Vec::new(),
|
||||
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
|
||||
|
|
|
|||
|
|
@ -2401,7 +2401,6 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
let git_config = builder.config.git_config();
|
||||
cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
|
||||
cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
|
||||
cmd.force_coloring_in_ci();
|
||||
|
||||
#[cfg(feature = "build-metrics")]
|
||||
builder.metrics.begin_test_suite(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ use std::env;
|
|||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use build_helper::ci::CiEnv;
|
||||
|
||||
use super::{Builder, Kind};
|
||||
use crate::core::build_steps::test;
|
||||
use crate::core::build_steps::tool::SourceType;
|
||||
|
|
@ -1334,7 +1336,13 @@ impl Builder<'_> {
|
|||
// Try to use a sysroot-relative bindir, in case it was configured absolutely.
|
||||
cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative());
|
||||
|
||||
cargo.force_coloring_in_ci();
|
||||
if CiEnv::is_ci() {
|
||||
// Tell cargo to use colored output for nicer logs in CI, even
|
||||
// though CI isn't printing to a terminal.
|
||||
// Also set an explicit `TERM=xterm` so that cargo doesn't warn
|
||||
// about TERM not being set.
|
||||
cargo.env("TERM", "xterm").args(["--color=always"]);
|
||||
};
|
||||
|
||||
// When we build Rust dylibs they're all intended for intermediate
|
||||
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use std::process::{
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use build_helper::ci::CiEnv;
|
||||
use build_helper::drop_bomb::DropBomb;
|
||||
use build_helper::exit;
|
||||
|
||||
|
|
@ -390,18 +389,6 @@ impl<'a> BootstrapCommand {
|
|||
self.drop_bomb.get_created_location()
|
||||
}
|
||||
|
||||
/// If in a CI environment, forces the command to run with colors.
|
||||
pub fn force_coloring_in_ci(&mut self) {
|
||||
if CiEnv::is_ci() {
|
||||
// Due to use of stamp/docker, the output stream of bootstrap is not
|
||||
// a TTY in CI, so coloring is by-default turned off.
|
||||
// The explicit `TERM=xterm` environment is needed for
|
||||
// `--color always` to actually work. This env var was lost when
|
||||
// compiling through the Makefile. Very strange.
|
||||
self.env("TERM", "xterm").args(["--color", "always"]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fingerprint(&self) -> CommandFingerprint {
|
||||
let command = &self.command;
|
||||
CommandFingerprint {
|
||||
|
|
|
|||
|
|
@ -136,8 +136,6 @@ fn parse_config(args: Vec<String>) -> Config {
|
|||
)
|
||||
.optflag("", "fail-fast", "stop as soon as possible after any test fails")
|
||||
.optopt("", "target", "the target to build for", "TARGET")
|
||||
// FIXME: Should be removed once `bootstrap` will be updated to not use this option.
|
||||
.optopt("", "color", "coloring: auto, always, never", "WHEN")
|
||||
.optopt("", "host", "the host to build for", "HOST")
|
||||
.optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
|
||||
.optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
|
||||
|
|
|
|||
14
tests/pretty/auxiliary/to-reuse-functions.rs
Normal file
14
tests/pretty/auxiliary/to-reuse-functions.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//@ edition:2021
|
||||
|
||||
#[must_use]
|
||||
#[cold]
|
||||
pub unsafe fn unsafe_fn_extern() -> usize { 1 }
|
||||
|
||||
#[must_use = "extern_fn_extern: some reason"]
|
||||
#[deprecated]
|
||||
pub extern "C" fn extern_fn_extern() -> usize { 1 }
|
||||
|
||||
pub const fn const_fn_extern() -> usize { 1 }
|
||||
|
||||
#[must_use]
|
||||
pub async fn async_fn_extern() { }
|
||||
61
tests/pretty/delegation-inherit-attributes.pp
Normal file
61
tests/pretty/delegation-inherit-attributes.pp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//@ edition:2021
|
||||
//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
|
||||
//@ pretty-mode:hir
|
||||
//@ pretty-compare-only
|
||||
//@ pp-exact:delegation-inherit-attributes.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(fn_delegation)]
|
||||
#[attr = MacroUse {arguments: UseAll}]
|
||||
extern crate std;
|
||||
#[prelude_import]
|
||||
use std::prelude::rust_2021::*;
|
||||
|
||||
extern crate to_reuse_functions;
|
||||
|
||||
mod to_reuse {
|
||||
#[attr = MustUse {reason: "foo: some reason"}]
|
||||
#[attr = Cold]
|
||||
fn foo(x: usize) -> usize { x }
|
||||
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
fn foo_no_reason(x: usize) -> usize { x }
|
||||
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Cold]
|
||||
fn bar(x: usize) -> usize { x }
|
||||
}
|
||||
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse {reason: "foo: some reason"}]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo1(arg0: _) -> _ { to_reuse::foo(self + 1) }
|
||||
|
||||
#[attr = MustUse]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo_no_reason(arg0: _) -> _ { to_reuse::foo_no_reason(self + 1) }
|
||||
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse {reason: "some reason"}]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo2(arg0: _) -> _ { to_reuse::foo(self + 1) }
|
||||
|
||||
#[attr = Inline(Hint)]
|
||||
fn bar(arg0: _) -> _ { to_reuse::bar(arg0) }
|
||||
|
||||
#[attr = MustUse]
|
||||
#[attr = Inline(Hint)]
|
||||
unsafe fn unsafe_fn_extern() -> _ { to_reuse_functions::unsafe_fn_extern() }
|
||||
#[attr = MustUse {reason: "extern_fn_extern: some reason"}]
|
||||
#[attr = Inline(Hint)]
|
||||
extern "C" fn extern_fn_extern()
|
||||
-> _ { to_reuse_functions::extern_fn_extern() }
|
||||
#[attr = Inline(Hint)]
|
||||
const fn const_fn_extern() -> _ { to_reuse_functions::const_fn_extern() }
|
||||
#[attr = MustUse {reason: "some reason"}]
|
||||
#[attr = Inline(Hint)]
|
||||
async fn async_fn_extern() -> _ { to_reuse_functions::async_fn_extern() }
|
||||
|
||||
|
||||
fn main() { }
|
||||
56
tests/pretty/delegation-inherit-attributes.rs
Normal file
56
tests/pretty/delegation-inherit-attributes.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//@ edition:2021
|
||||
//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
|
||||
//@ pretty-mode:hir
|
||||
//@ pretty-compare-only
|
||||
//@ pp-exact:delegation-inherit-attributes.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(fn_delegation)]
|
||||
|
||||
extern crate to_reuse_functions;
|
||||
|
||||
mod to_reuse {
|
||||
#[must_use = "foo: some reason"]
|
||||
#[cold]
|
||||
pub fn foo(x: usize) -> usize {
|
||||
x
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[cold]
|
||||
pub fn foo_no_reason(x: usize) -> usize {
|
||||
x
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[deprecated]
|
||||
pub fn bar(x: usize) -> usize {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
reuse to_reuse::foo as foo1 {
|
||||
self + 1
|
||||
}
|
||||
|
||||
reuse to_reuse::foo_no_reason {
|
||||
self + 1
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[must_use = "some reason"]
|
||||
reuse to_reuse::foo as foo2 {
|
||||
self + 1
|
||||
}
|
||||
|
||||
reuse to_reuse::bar;
|
||||
|
||||
reuse to_reuse_functions::unsafe_fn_extern;
|
||||
reuse to_reuse_functions::extern_fn_extern;
|
||||
reuse to_reuse_functions::const_fn_extern;
|
||||
#[must_use = "some reason"]
|
||||
reuse to_reuse_functions::async_fn_extern;
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -14,10 +14,7 @@ LL | struct Foo {
|
|||
| ---------- method `bar` not found for this struct
|
||||
...
|
||||
LL | Foo { baz: 0 }.bar();
|
||||
| ---------------^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `Foo::bar()`
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `Foo`
|
||||
|
|
@ -25,6 +22,11 @@ note: the candidate is defined in an impl for the type `Foo`
|
|||
|
|
||||
LL | fn bar() {
|
||||
| ^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - Foo { baz: 0 }.bar();
|
||||
LL + Foo::bar();
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
10
tests/ui/methods/assc-func-issue-149038.rs
Normal file
10
tests/ui/methods/assc-func-issue-149038.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
struct S;
|
||||
impl S {
|
||||
fn foo() {}
|
||||
fn bar(&self) {
|
||||
self.foo(); //~ ERROR no method named `foo` found for reference `&S` in the current scope
|
||||
let f: fn() = self.foo; //~ ERROR no field `foo` on type `&S`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
43
tests/ui/methods/assc-func-issue-149038.stderr
Normal file
43
tests/ui/methods/assc-func-issue-149038.stderr
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
error[E0599]: no method named `foo` found for reference `&S` in the current scope
|
||||
--> $DIR/assc-func-issue-149038.rs:5:14
|
||||
|
|
||||
LL | self.foo();
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `S`
|
||||
--> $DIR/assc-func-issue-149038.rs:3:5
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| ^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - self.foo();
|
||||
LL + S::foo();
|
||||
|
|
||||
|
||||
error[E0609]: no field `foo` on type `&S`
|
||||
--> $DIR/assc-func-issue-149038.rs:6:28
|
||||
|
|
||||
LL | let f: fn() = self.foo;
|
||||
| ^^^
|
||||
| |
|
||||
| this is an associated function, not a method
|
||||
| unknown field
|
||||
|
|
||||
= note: found the following associated function; to be used as method, it must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `S`
|
||||
--> $DIR/assc-func-issue-149038.rs:3:5
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| ^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - let f: fn() = self.foo;
|
||||
LL + let f: fn() = S::foo;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0599, E0609.
|
||||
For more information about an error, try `rustc --explain E0599`.
|
||||
|
|
@ -2,10 +2,7 @@ error[E0599]: no method named `boom` found for reference `&Obj` in the current s
|
|||
--> $DIR/issue-3707.rs:10:14
|
||||
|
|
||||
LL | self.boom();
|
||||
| -----^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `Obj::boom()`
|
||||
| ^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `Obj`
|
||||
|
|
@ -13,6 +10,11 @@ note: the candidate is defined in an impl for the type `Obj`
|
|||
|
|
||||
LL | pub fn boom() -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - self.boom();
|
||||
LL + Obj::boom();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
17
tests/ui/resolve/ice-inconsistent-resolution-149821.rs
Normal file
17
tests/ui/resolve/ice-inconsistent-resolution-149821.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
//@ edition: 2024
|
||||
|
||||
mod m {
|
||||
use crate::*;
|
||||
use core;
|
||||
}
|
||||
|
||||
macro_rules! define_other_core {
|
||||
() => {
|
||||
extern crate std as core;
|
||||
//~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||
};
|
||||
}
|
||||
|
||||
define_other_core! {}
|
||||
|
||||
fn main() {}
|
||||
13
tests/ui/resolve/ice-inconsistent-resolution-149821.stderr
Normal file
13
tests/ui/resolve/ice-inconsistent-resolution-149821.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||
--> $DIR/ice-inconsistent-resolution-149821.rs:10:9
|
||||
|
|
||||
LL | extern crate std as core;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | define_other_core! {}
|
||||
| --------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -2,10 +2,7 @@ error[E0599]: no method named `func` found for type `i32` in the current scope
|
|||
--> $DIR/issue-102354.rs:9:7
|
||||
|
|
||||
LL | x.func();
|
||||
| --^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `i32::func()`
|
||||
| ^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in the trait `Trait`
|
||||
|
|
@ -13,6 +10,11 @@ note: the candidate is defined in the trait `Trait`
|
|||
|
|
||||
LL | fn func() {}
|
||||
| ^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - x.func();
|
||||
LL + i32::func();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ error[E0599]: no method named `nya` found for type parameter `T` in the current
|
|||
LL | fn uwu<T: Cat>(c: T) {
|
||||
| - method `nya` not found for this type parameter
|
||||
LL | c.nya();
|
||||
| --^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `T::nya()`
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in the trait `Cat`
|
||||
|
|
@ -15,6 +12,11 @@ note: the candidate is defined in the trait `Cat`
|
|||
|
|
||||
LL | fn nya() {}
|
||||
| ^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - c.nya();
|
||||
LL + T::nya();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ error[E0599]: no method named `test` found for struct `Box<Foo<i32>>` in the cur
|
|||
--> $DIR/suggest-assoc-fn-call-deref.rs:13:7
|
||||
|
|
||||
LL | x.test();
|
||||
| --^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `Foo::<i32>::test()`
|
||||
| ^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `Foo<T>`
|
||||
|
|
@ -13,6 +10,11 @@ note: the candidate is defined in an impl for the type `Foo<T>`
|
|||
|
|
||||
LL | fn test() -> i32 { 1 }
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - x.test();
|
||||
LL + Foo::<i32>::test();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ LL | struct A {
|
|||
| -------- method `foo` not found for this struct
|
||||
...
|
||||
LL | _a.foo();
|
||||
| ---^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::foo(_a)`
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in the trait `M`
|
||||
|
|
@ -16,6 +13,11 @@ note: the candidate is defined in the trait `M`
|
|||
|
|
||||
LL | fn foo(_a: Self);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _a.foo();
|
||||
LL + A::foo(_a);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `baz` found for struct `A` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:23:8
|
||||
|
|
@ -24,10 +26,7 @@ LL | struct A {
|
|||
| -------- method `baz` not found for this struct
|
||||
...
|
||||
LL | _a.baz(0);
|
||||
| ---^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::baz(0)`
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in the trait `M`
|
||||
|
|
@ -35,6 +34,11 @@ note: the candidate is defined in the trait `M`
|
|||
|
|
||||
LL | fn baz(_a: i32);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _a.baz(0);
|
||||
LL + A::baz(0);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `bar` found for struct `A` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:27:8
|
||||
|
|
@ -43,10 +47,7 @@ LL | struct A {
|
|||
| -------- method `bar` not found for this struct
|
||||
...
|
||||
LL | _b.bar();
|
||||
| ---^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::bar(_b)`
|
||||
| ^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in the trait `M`
|
||||
|
|
@ -54,6 +55,11 @@ note: the candidate is defined in the trait `M`
|
|||
|
|
||||
LL | fn bar(_a: Self);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _b.bar();
|
||||
LL + A::bar(_b);
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `default_hello` not found for this struct
|
||||
...
|
||||
LL | x.default_hello();
|
||||
| --^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()`
|
||||
| ^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -16,6 +13,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn default_hello() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - x.default_hello();
|
||||
LL + GenericAssocMethod::<_>::default_hello();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMetho
|
|||
--> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
|
||||
|
|
||||
LL | state.hello();
|
||||
| ------^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `HasAssocMethod::hello()`
|
||||
| ^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `HasAssocMethod`
|
||||
|
|
@ -13,6 +10,11 @@ note: the candidate is defined in an impl for the type `HasAssocMethod`
|
|||
|
|
||||
LL | fn hello() {}
|
||||
| ^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - state.hello();
|
||||
LL + HasAssocMethod::hello();
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `self_ty_ref_hello` not found for this struct
|
||||
...
|
||||
LL | x.self_ty_ref_hello();
|
||||
| --^^^^^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)`
|
||||
| ^^^^^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -16,6 +13,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn self_ty_ref_hello(_: &Self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - x.self_ty_ref_hello();
|
||||
LL + GenericAssocMethod::<_>::self_ty_ref_hello(&x);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7
|
||||
|
|
@ -24,10 +26,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `self_ty_hello` not found for this struct
|
||||
...
|
||||
LL | x.self_ty_hello();
|
||||
| --^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)`
|
||||
| ^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -35,6 +34,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn self_ty_hello(_: Self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - x.self_ty_hello();
|
||||
LL + GenericAssocMethod::<_>::self_ty_hello(x);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7
|
||||
|
|
@ -43,10 +47,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `default_hello` not found for this struct
|
||||
...
|
||||
LL | y.default_hello();
|
||||
| --^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello()`
|
||||
| ^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -54,6 +55,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn default_hello() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - y.default_hello();
|
||||
LL + GenericAssocMethod::<i32>::default_hello();
|
||||
|
|
||||
|
||||
error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<i32>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7
|
||||
|
|
@ -62,10 +68,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `self_ty_ref_hello` not found for this struct
|
||||
...
|
||||
LL | y.self_ty_ref_hello();
|
||||
| --^^^^^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_ref_hello(&y)`
|
||||
| ^^^^^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -73,6 +76,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn self_ty_ref_hello(_: &Self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - y.self_ty_ref_hello();
|
||||
LL + GenericAssocMethod::<i32>::self_ty_ref_hello(&y);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<i32>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7
|
||||
|
|
@ -81,10 +89,7 @@ LL | struct GenericAssocMethod<T>(T);
|
|||
| ---------------------------- method `self_ty_hello` not found for this struct
|
||||
...
|
||||
LL | y.self_ty_hello();
|
||||
| --^^^^^^^^^^^^^--
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_hello(y)`
|
||||
| ^^^^^^^^^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
||||
|
|
@ -92,6 +97,11 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
|
|||
|
|
||||
LL | fn self_ty_hello(_: Self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - y.self_ty_hello();
|
||||
LL + GenericAssocMethod::<i32>::self_ty_hello(y);
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ LL | struct A {}
|
|||
| -------- method `hello` not found for this struct
|
||||
...
|
||||
LL | _a.hello(1);
|
||||
| ---^^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::hello(1)`
|
||||
| ^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `A`
|
||||
|
|
@ -16,6 +13,11 @@ note: the candidate is defined in an impl for the type `A`
|
|||
|
|
||||
LL | fn hello(_a: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _a.hello(1);
|
||||
LL + A::hello(1);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `test` found for struct `A` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:22:8
|
||||
|
|
@ -24,10 +26,7 @@ LL | struct A {}
|
|||
| -------- method `test` not found for this struct
|
||||
...
|
||||
LL | _a.test(1);
|
||||
| ---^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::test(_a, 1)`
|
||||
| ^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `A`
|
||||
|
|
@ -35,6 +34,11 @@ note: the candidate is defined in an impl for the type `A`
|
|||
|
|
||||
LL | fn test(_a: Self, _b: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _a.test(1);
|
||||
LL + A::test(_a, 1);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `hello` found for struct `B<&str>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:26:8
|
||||
|
|
@ -43,10 +47,7 @@ LL | struct B<T> {
|
|||
| ----------- method `hello` not found for this struct
|
||||
...
|
||||
LL | _b.hello(1);
|
||||
| ---^^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `B::<&str>::hello(1)`
|
||||
| ^^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `B<T>`
|
||||
|
|
@ -54,6 +55,11 @@ note: the candidate is defined in an impl for the type `B<T>`
|
|||
|
|
||||
LL | fn hello(_a: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _b.hello(1);
|
||||
LL + B::<&str>::hello(1);
|
||||
|
|
||||
|
||||
error[E0599]: no method named `test` found for struct `B<&str>` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:28:8
|
||||
|
|
@ -62,10 +68,7 @@ LL | struct B<T> {
|
|||
| ----------- method `test` not found for this struct
|
||||
...
|
||||
LL | _b.test(1);
|
||||
| ---^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `B::<&str>::test(_b, 1)`
|
||||
| ^^^^ this is an associated function, not a method
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `B<T>`
|
||||
|
|
@ -73,6 +76,11 @@ note: the candidate is defined in an impl for the type `B<T>`
|
|||
|
|
||||
LL | fn test(_a: Self, _b: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use associated function syntax instead
|
||||
|
|
||||
LL - _b.test(1);
|
||||
LL + B::<&str>::test(_b, 1);
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue