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:
bors 2025-12-13 07:00:41 +00:00
commit ce63e5d9ea
85 changed files with 904 additions and 846 deletions

View file

@ -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,

View file

@ -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 }

View file

@ -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)]

View file

@ -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

View file

@ -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

View file

@ -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();
}
}

View file

@ -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,
})
}
}
}

View file

@ -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;

View file

@ -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;
};

View file

@ -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};

View file

@ -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 {

View file

@ -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>,

View file

@ -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() {

View file

@ -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.

View file

@ -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] } => {

View file

@ -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);

View file

@ -2,6 +2,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]

View file

@ -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)));

View file

@ -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;
};

View file

@ -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 } => {

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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 {

View file

@ -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)]

View file

@ -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]

View file

@ -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`):

View file

@ -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 {

View file

@ -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)]

View file

@ -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);

View file

@ -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))
}
};

View file

@ -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);

View file

@ -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);

View file

@ -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)]

View file

@ -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;
};

View file

@ -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
}
};

View file

@ -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()

View file

@ -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 });

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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,
};

View file

@ -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),
};

View file

@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]

View file

@ -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);

View file

@ -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;

View file

@ -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)]

View file

@ -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 {

View file

@ -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,

View file

@ -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)]

View file

@ -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, .. }) => {

View file

@ -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();
};

View file

@ -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();
}
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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)?;

View file

@ -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) };
}
}

View file

@ -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.

View file

@ -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).

View file

@ -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");
}
}

View file

@ -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

View file

@ -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() {

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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.

View file

@ -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(

View file

@ -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

View file

@ -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 {

View file

@ -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")

View 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() { }

View 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() { }

View 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() {}

View file

@ -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

View 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() {}

View 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`.

View file

@ -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

View 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() {}

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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