Auto merge of #145020 - GuillaumeGomez:rollup-5prs9kw, r=GuillaumeGomez

Rollup of 15 pull requests

Successful merges:

 - rust-lang/rust#144195 (Parser: Recover from attributes applied to types and generic args)
 - rust-lang/rust#144794 (Port `#[coroutine]` to the new attribute system)
 - rust-lang/rust#144835 (Anonymize binders in tail call sig)
 - rust-lang/rust#144861 (Stabilize `panic_payload_as_str` feature)
 - rust-lang/rust#144917 (Enforce tail call type is related to body return type in borrowck)
 - rust-lang/rust#144948 (we only merge candidates for trait and normalizes-to goals)
 - rust-lang/rust#144956 (Gate const trait syntax)
 - rust-lang/rust#144970 (rustdoc: fix caching of intra-doc links on reexports)
 - rust-lang/rust#144972 (add code example showing that file_prefix treats dotfiles as the name of a file, not an extension)
 - rust-lang/rust#144975 (`File::set_times`: Update documentation and example to support setting timestamps on directories)
 - rust-lang/rust#144977 (Fortify generic param default checks)
 - rust-lang/rust#144996 (simplifycfg: Mark as changed when start is modified in collapse goto chain)
 - rust-lang/rust#144998 (mir: Do not modify NonUse in `super_projection_elem`)
 - rust-lang/rust#145000 (Remove unneeded `stage` parameter when setting up stdlib Cargo)
 - rust-lang/rust#145008 (Fix rustdoc scrape examples crash)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-08-06 23:23:26 +00:00
commit 6bcdcc73bd
83 changed files with 1054 additions and 502 deletions

View file

@ -98,7 +98,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let expr_hir_id = self.lower_node_id(e.id);
self.lower_attrs(expr_hir_id, &e.attrs, e.span);
let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span);
let kind = match &e.kind {
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@ -232,10 +232,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
*fn_arg_span,
),
None => self.lower_expr_closure(
attrs,
binder,
*capture_clause,
e.id,
expr_hir_id,
*constness,
*movability,
fn_decl,
@ -1052,10 +1052,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_expr_closure(
&mut self,
attrs: &[rustc_hir::Attribute],
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
closure_hir_id: hir::HirId,
constness: Const,
movability: Movability,
decl: &FnDecl,
@ -1067,15 +1067,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
let mut coroutine_kind = if this
.attrs
.get(&closure_hir_id.local_id)
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
{
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
} else {
None
};
let mut coroutine_kind = find_attr!(attrs, AttributeKind::Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable));
// FIXME(contracts): Support contracts on closures?
let body_id = this.lower_fn_body(decl, None, |this| {
this.coroutine_kind = coroutine_kind;

View file

@ -0,0 +1,15 @@
//! Attributes that can be found in function body.
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use super::{NoArgsAttributeParser, OnDuplicate};
use crate::context::Stage;
pub(crate) struct CoroutineParser;
impl<S: Stage> NoArgsAttributeParser<S> for CoroutineParser {
const PATH: &[Symbol] = &[sym::coroutine];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Coroutine(span);
}

View file

@ -26,6 +26,7 @@ use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;
pub(crate) mod allow_unstable;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod codegen_attrs;

View file

@ -16,6 +16,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
use crate::attributes::allow_unstable::{
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
};
use crate::attributes::body::CoroutineParser;
use crate::attributes::codegen_attrs::{
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser,
TargetFeatureParser, TrackCallerParser, UsedParser,
@ -184,6 +185,7 @@ attribute_parsers!(
Single<WithoutArgs<ConstContinueParser>>,
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<ConstTraitParser>>,
Single<WithoutArgs<CoroutineParser>>,
Single<WithoutArgs<DenyExplicitImplParser>>,
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
Single<WithoutArgs<ExportStableParser>>,

View file

@ -769,9 +769,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
TerminatorKind::Call { func, args, .. }
| TerminatorKind::TailCall { func, args, .. } => {
let call_source = match term.kind {
TerminatorKind::Call { call_source, .. } => call_source,
TerminatorKind::TailCall { .. } => CallSource::Normal,
let (call_source, destination, is_diverging) = match term.kind {
TerminatorKind::Call { call_source, destination, target, .. } => {
(call_source, destination, target.is_none())
}
TerminatorKind::TailCall { .. } => {
(CallSource::Normal, RETURN_PLACE.into(), false)
}
_ => unreachable!(),
};
@ -845,9 +849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);
}
if let TerminatorKind::Call { destination, target, .. } = term.kind {
self.check_call_dest(term, &sig, destination, target, term_location);
}
self.check_call_dest(term, &sig, destination, is_diverging, term_location);
// The ordinary liveness rules will ensure that all
// regions in the type of the callee are live here. We
@ -1874,65 +1876,61 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
destination: Place<'tcx>,
target: Option<BasicBlock>,
is_diverging: bool,
term_location: Location,
) {
let tcx = self.tcx();
match target {
Some(_) => {
let dest_ty = destination.ty(self.body, tcx).ty;
let dest_ty = self.normalize(dest_ty, term_location);
let category = match destination.as_local() {
Some(RETURN_PLACE) => {
if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
self.universal_regions.defining_ty
{
if tcx.is_static(def_id) {
ConstraintCategory::UseAsStatic
} else {
ConstraintCategory::UseAsConst
}
} else {
ConstraintCategory::Return(ReturnConstraint::Normal)
}
}
Some(l) if !self.body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring
}
// The return type of a call is interesting for diagnostics.
_ => ConstraintCategory::Assignment,
};
let locations = term_location.to_locations();
if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
span_mirbug!(
self,
term,
"call dest mismatch ({:?} <- {:?}): {:?}",
dest_ty,
sig.output(),
terr
);
}
// When `unsized_fn_params` is not enabled,
// this check is done at `check_local`.
if self.unsized_feature_enabled() {
let span = term.source_info.span;
self.ensure_place_sized(dest_ty, span);
}
if is_diverging {
// The signature in this call can reference region variables,
// so erase them before calling a query.
let output_ty = self.tcx().erase_regions(sig.output());
if !output_ty
.is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
{
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
None => {
// The signature in this call can reference region variables,
// so erase them before calling a query.
let output_ty = self.tcx().erase_regions(sig.output());
if !output_ty.is_privately_uninhabited(
self.tcx(),
self.infcx.typing_env(self.infcx.param_env),
) {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
} else {
let dest_ty = destination.ty(self.body, tcx).ty;
let dest_ty = self.normalize(dest_ty, term_location);
let category = match destination.as_local() {
Some(RETURN_PLACE) => {
if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
self.universal_regions.defining_ty
{
if tcx.is_static(def_id) {
ConstraintCategory::UseAsStatic
} else {
ConstraintCategory::UseAsConst
}
} else {
ConstraintCategory::Return(ReturnConstraint::Normal)
}
}
Some(l) if !self.body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring
}
// The return type of a call is interesting for diagnostics.
_ => ConstraintCategory::Assignment,
};
let locations = term_location.to_locations();
if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
span_mirbug!(
self,
term,
"call dest mismatch ({:?} <- {:?}): {:?}",
dest_ty,
sig.output(),
terr
);
}
// When `unsized_fn_params` is not enabled,
// this check is done at `check_local`.
if self.unsized_feature_enabled() {
let span = term.source_info.span;
self.ensure_place_sized(dest_ty, span);
}
}
}

View file

@ -297,6 +297,9 @@ pub enum AttributeKind {
/// Represents `#[const_trait]`.
ConstTrait(Span),
/// Represents `#[coroutine]`.
Coroutine(Span),
/// Represents `#[coverage(..)]`.
Coverage(Span, CoverageAttrKind),

View file

@ -28,6 +28,7 @@ impl AttributeKind {
ConstStability { .. } => Yes,
ConstStabilityIndirect => No,
ConstTrait(..) => No,
Coroutine(..) => No,
Coverage(..) => No,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,

View file

@ -223,60 +223,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
"synthetic HIR should have its `generics_of` explicitly fed"
),
_ => span_bug!(tcx.def_span(def_id), "unhandled node {node:?}"),
_ => span_bug!(tcx.def_span(def_id), "generics_of: unexpected node kind {node:?}"),
};
enum Defaults {
Allowed,
// See #36887
FutureCompatDisallowed,
Deny,
}
// Add in the self type parameter.
let opt_self = if let Node::Item(item) = node
&& let ItemKind::Trait(..) | ItemKind::TraitAlias(..) = item.kind
{
// Something of a hack: We reuse the node ID of the trait for the self type parameter.
Some(ty::GenericParamDef {
index: 0,
name: kw::SelfUpper,
def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
})
} else {
None
};
let param_default_policy = param_default_policy(node);
let hir_generics = node.generics().unwrap_or(hir::Generics::empty());
let (opt_self, allow_defaults) = match node {
Node::Item(item) => {
match item.kind {
ItemKind::Trait(..) | ItemKind::TraitAlias(..) => {
// Add in the self type parameter.
//
// Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter.
let opt_self = Some(ty::GenericParamDef {
index: 0,
name: kw::SelfUpper,
def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
synthetic: false,
},
});
(opt_self, Defaults::Allowed)
}
ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::Union(..) => (None, Defaults::Allowed),
ItemKind::Const(..) => (None, Defaults::Deny),
_ => (None, Defaults::FutureCompatDisallowed),
}
}
Node::OpaqueTy(..) => (None, Defaults::Allowed),
// GATs
Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
(None, Defaults::Deny)
}
Node::ImplItem(item) if matches!(item.kind, ImplItemKind::Type(..)) => {
(None, Defaults::Deny)
}
_ => (None, Defaults::FutureCompatDisallowed),
};
let has_self = opt_self.is_some();
let mut parent_has_self = false;
let mut own_start = has_self as u32;
@ -312,60 +279,53 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
prev + type_start
};
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions";
own_params.extend(hir_generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { default, synthetic, .. } => {
if default.is_some() {
match allow_defaults {
Defaults::Allowed => {}
Defaults::FutureCompatDisallowed => {
tcx.node_span_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
|lint| {
lint.primary_message(TYPE_DEFAULT_NOT_ALLOWED);
},
);
}
Defaults::Deny => {
tcx.dcx().span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
own_params.extend(hir_generics.params.iter().filter_map(|param| {
const MESSAGE: &str = "defaults for generic parameters are not allowed here";
let kind = match param.kind {
GenericParamKind::Lifetime { .. } => return None,
GenericParamKind::Type { default, synthetic } => {
if default.is_some() {
match param_default_policy.expect("no policy for generic param default") {
ParamDefaultPolicy::Allowed => {}
ParamDefaultPolicy::FutureCompatForbidden => {
tcx.node_span_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
|lint| {
lint.primary_message(MESSAGE);
},
);
}
ParamDefaultPolicy::Forbidden => {
tcx.dcx().span_err(param.span, MESSAGE);
}
}
}
ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }
}
GenericParamKind::Const { ty: _, default, synthetic } => {
if default.is_some() {
match param_default_policy.expect("no policy for generic param default") {
ParamDefaultPolicy::Allowed => {}
ParamDefaultPolicy::FutureCompatForbidden
| ParamDefaultPolicy::Forbidden => {
tcx.dcx().span_err(param.span, MESSAGE);
}
}
}
let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
Some(ty::GenericParamDef {
index: next_index(),
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind,
})
}
GenericParamKind::Const { ty: _, default, synthetic } => {
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
tcx.dcx().span_err(
param.span,
"defaults for const parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions",
);
ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic }
}
let index = next_index();
Some(ty::GenericParamDef {
index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic },
})
}
};
Some(ty::GenericParamDef {
index: next_index(),
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind,
})
}));
// provide junk type parameter defs - the only place that
@ -438,6 +398,48 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
}
#[derive(Clone, Copy)]
enum ParamDefaultPolicy {
Allowed,
/// Tracked in <https://github.com/rust-lang/rust/issues/36887>.
FutureCompatForbidden,
Forbidden,
}
fn param_default_policy(node: Node<'_>) -> Option<ParamDefaultPolicy> {
use rustc_hir::*;
Some(match node {
Node::Item(item) => match item.kind {
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
| ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::Union(..) => ParamDefaultPolicy::Allowed,
ItemKind::Fn { .. } | ItemKind::Impl(_) => ParamDefaultPolicy::FutureCompatForbidden,
// Re. GCI, we're not bound by backward compatibility.
ItemKind::Const(..) => ParamDefaultPolicy::Forbidden,
_ => return None,
},
Node::TraitItem(item) => match item.kind {
// Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility.
TraitItemKind::Const(..) | TraitItemKind::Type(..) => ParamDefaultPolicy::Forbidden,
TraitItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden,
},
Node::ImplItem(item) => match item.kind {
// Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility.
ImplItemKind::Const(..) | ImplItemKind::Type(..) => ParamDefaultPolicy::Forbidden,
ImplItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden,
},
// Generic params are (semantically) invalid on foreign items. Still, for maximum forward
// compatibility, let's hard-reject defaults on them.
Node::ForeignItem(_) => ParamDefaultPolicy::Forbidden,
Node::OpaqueTy(..) => ParamDefaultPolicy::Allowed,
_ => return None,
})
}
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
struct LateBoundRegionsDetector<'tcx> {
tcx: TyCtxt<'tcx>,

View file

@ -1205,18 +1205,19 @@ macro_rules! visit_place_fns {
self.super_projection_elem(place_ref, elem, context, location);
}
fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
let mut context = context;
if !place.projection.is_empty() {
if context.is_use() {
// ^ Only change the context if it is a real use, not a "use" in debuginfo.
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
};
}
fn super_place(
&mut self,
place: &Place<'tcx>,
mut context: PlaceContext,
location: Location,
) {
if !place.projection.is_empty() && context.is_use() {
// ^ Only change the context if it is a real use, not a "use" in debuginfo.
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
};
}
self.visit_local(place.local, context, location);
@ -1239,7 +1240,7 @@ macro_rules! visit_place_fns {
&mut self,
_place_ref: PlaceRef<'tcx>,
elem: PlaceElem<'tcx>,
_context: PlaceContext,
context: PlaceContext,
location: Location,
) {
match elem {
@ -1252,7 +1253,12 @@ macro_rules! visit_place_fns {
ProjectionElem::Index(local) => {
self.visit_local(
local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
if context.is_use() {
// ^ Only change the context if it is a real use, not a "use" in debuginfo.
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)
} else {
context
},
location,
);
}

View file

@ -60,9 +60,13 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
let BodyTy::Fn(caller_sig) = self.thir.body_type else {
span_bug!(
call.span,
"`become` outside of functions should have been disallowed by hit_typeck"
"`become` outside of functions should have been disallowed by hir_typeck"
)
};
// While the `caller_sig` does have its regions erased, it does not have its
// binders anonymized. We call `erase_regions` once again to anonymize any binders
// within the signature, such as in function pointer or `dyn Trait` args.
let caller_sig = self.tcx.erase_regions(caller_sig);
let ExprKind::Scope { value, .. } = call.kind else {
span_bug!(call.span, "expected scope, found: {call:?}")

View file

@ -225,6 +225,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
current = target;
}
let last = current;
*changed |= *start != last;
*start = last;
while let Some((current, mut terminator)) = terminators.pop() {
let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator

View file

@ -959,36 +959,23 @@ where
// Even when a trait bound has been proven using a where-bound, we
// still need to consider alias-bounds for normalization, see
// `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
let candidates_from_env_and_bounds: Vec<_> = self
let mut candidates: Vec<_> = self
.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::EnvAndBounds);
// We still need to prefer where-bounds over alias-bounds however.
// See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
let mut considered_candidates: Vec<_> = if candidates_from_env_and_bounds
.iter()
.any(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
{
candidates_from_env_and_bounds
.into_iter()
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
.map(|c| c.result)
.collect()
} else {
candidates_from_env_and_bounds.into_iter().map(|c| c.result).collect()
};
// If the trait goal has been proven by using the environment, we want to treat
// aliases as rigid if there are no applicable projection bounds in the environment.
if considered_candidates.is_empty() {
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
considered_candidates.push(response);
}
if candidates.iter().any(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
candidates.retain(|c| matches!(c.source, CandidateSource::ParamEnv(_)));
} else if candidates.is_empty() {
// If the trait goal has been proven by using the environment, we want to treat
// aliases as rigid if there are no applicable projection bounds in the environment.
return inject_normalize_to_rigid_candidate(self);
}
if let Some(response) = self.try_merge_responses(&considered_candidates) {
if let Some(response) = self.try_merge_candidates(&candidates) {
Ok(response)
} else {
self.flounder(&considered_candidates)
self.flounder(&candidates)
}
}
TraitGoalProvenVia::Misc => {
@ -998,11 +985,9 @@ where
// Prefer "orphaned" param-env normalization predicates, which are used
// (for example, and ideally only) when proving item bounds for an impl.
let candidates_from_env: Vec<_> = candidates
.iter()
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
.map(|c| c.result)
.extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
.collect();
if let Some(response) = self.try_merge_responses(&candidates_from_env) {
if let Some(response) = self.try_merge_candidates(&candidates_from_env) {
return Ok(response);
}
@ -1012,12 +997,10 @@ where
// means we can just ignore inference constraints and don't have to special-case
// constraining the normalized-to `term`.
self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates);
let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
if let Some(response) = self.try_merge_responses(&responses) {
if let Some(response) = self.try_merge_candidates(&candidates) {
Ok(response)
} else {
self.flounder(&responses)
self.flounder(&candidates)
}
}
}

View file

@ -29,6 +29,7 @@ use tracing::instrument;
pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
use crate::delegate::SolverDelegate;
use crate::solve::assembly::Candidate;
/// How many fixpoint iterations we should attempt inside of the solver before bailing
/// with overflow.
@ -244,50 +245,51 @@ where
///
/// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
#[instrument(level = "trace", skip(self), ret)]
fn try_merge_responses(
fn try_merge_candidates(
&mut self,
responses: &[CanonicalResponse<I>],
candidates: &[Candidate<I>],
) -> Option<CanonicalResponse<I>> {
if responses.is_empty() {
if candidates.is_empty() {
return None;
}
let one = responses[0];
if responses[1..].iter().all(|&resp| resp == one) {
let one: CanonicalResponse<I> = candidates[0].result;
if candidates[1..].iter().all(|candidate| candidate.result == one) {
return Some(one);
}
responses
candidates
.iter()
.find(|response| {
response.value.certainty == Certainty::Yes
&& has_no_inference_or_external_constraints(**response)
.find(|candidate| {
candidate.result.value.certainty == Certainty::Yes
&& has_no_inference_or_external_constraints(candidate.result)
})
.copied()
.map(|candidate| candidate.result)
}
fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse<I>]) -> CanonicalResponse<I> {
debug_assert!(responses.len() > 1);
let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| {
// Pull down the certainty of `Certainty::Yes` to ambiguity when combining
// these responses, b/c we're combining more than one response and this we
// don't know which one applies.
let candidate = match response.value.certainty {
Certainty::Yes => MaybeCause::Ambiguity,
Certainty::Maybe(candidate) => candidate,
};
maybe_cause.or(candidate)
});
fn bail_with_ambiguity(&mut self, candidates: &[Candidate<I>]) -> CanonicalResponse<I> {
debug_assert!(candidates.len() > 1);
let maybe_cause =
candidates.iter().fold(MaybeCause::Ambiguity, |maybe_cause, candidates| {
// Pull down the certainty of `Certainty::Yes` to ambiguity when combining
// these responses, b/c we're combining more than one response and this we
// don't know which one applies.
let candidate = match candidates.result.value.certainty {
Certainty::Yes => MaybeCause::Ambiguity,
Certainty::Maybe(candidate) => candidate,
};
maybe_cause.or(candidate)
});
self.make_ambiguous_response_no_constraints(maybe_cause)
}
/// If we fail to merge responses we flounder and return overflow or ambiguity.
#[instrument(level = "trace", skip(self), ret)]
fn flounder(&mut self, responses: &[CanonicalResponse<I>]) -> QueryResult<I> {
if responses.is_empty() {
fn flounder(&mut self, candidates: &[Candidate<I>]) -> QueryResult<I> {
if candidates.is_empty() {
return Err(NoSolution);
} else {
Ok(self.bail_with_ambiguity(responses))
Ok(self.bail_with_ambiguity(candidates))
}
}

View file

@ -1346,11 +1346,10 @@ where
mut candidates: Vec<Candidate<I>>,
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
if let TypingMode::Coherence = self.typing_mode() {
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
return if let Some(response) = self.try_merge_responses(&all_candidates) {
return if let Some(response) = self.try_merge_candidates(&candidates) {
Ok((response, Some(TraitGoalProvenVia::Misc)))
} else {
self.flounder(&all_candidates).map(|r| (r, None))
self.flounder(&candidates).map(|r| (r, None))
};
}
@ -1375,11 +1374,9 @@ where
.any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
if has_non_global_where_bounds {
let where_bounds: Vec<_> = candidates
.iter()
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
.map(|c| c.result)
.extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
.collect();
return if let Some(response) = self.try_merge_responses(&where_bounds) {
return if let Some(response) = self.try_merge_candidates(&where_bounds) {
Ok((response, Some(TraitGoalProvenVia::ParamEnv)))
} else {
Ok((self.bail_with_ambiguity(&where_bounds), None))
@ -1388,11 +1385,9 @@ where
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) {
let alias_bounds: Vec<_> = candidates
.iter()
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
.map(|c| c.result)
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound))
.collect();
return if let Some(response) = self.try_merge_responses(&alias_bounds) {
return if let Some(response) = self.try_merge_candidates(&alias_bounds) {
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
} else {
Ok((self.bail_with_ambiguity(&alias_bounds), None))
@ -1417,11 +1412,10 @@ where
TraitGoalProvenVia::Misc
};
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
if let Some(response) = self.try_merge_responses(&all_candidates) {
if let Some(response) = self.try_merge_candidates(&candidates) {
Ok((response, Some(proven_via)))
} else {
self.flounder(&all_candidates).map(|r| (r, None))
self.flounder(&candidates).map(|r| (r, None))
}
}

View file

@ -71,6 +71,17 @@ parse_attr_without_generics = attribute without generic parameters
parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
.label = attributes are not allowed here
parse_attribute_on_type = attributes cannot be applied to types
.label = attributes are not allowed here
.suggestion = remove attribute from here
parse_attribute_on_generic_arg = attributes cannot be applied to generic arguments
.label = attributes are not allowed here
.suggestion = remove attribute from here
parse_attribute_on_empty_type = attributes cannot be applied here
.label = attributes are not allowed here
parse_bad_assoc_type_bounds = bounds on associated types do not belong here
.label = belongs in `where` clause

View file

@ -1489,6 +1489,34 @@ pub(crate) struct AttributeOnParamType {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_attribute_on_type)]
pub(crate) struct AttributeOnType {
#[primary_span]
#[label]
pub span: Span,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub fix_span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_attribute_on_generic_arg)]
pub(crate) struct AttributeOnGenericArg {
#[primary_span]
#[label]
pub span: Span,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub fix_span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_attribute_on_empty_type)]
pub(crate) struct AttributeOnEmptyType {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_pattern_method_param_without_body, code = E0642)]
pub(crate) struct PatternMethodParamWithoutBody {

View file

@ -885,6 +885,9 @@ impl<'a> Parser<'a> {
/// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
let constness = self.parse_constness(Case::Sensitive);
if let Const::Yes(span) = constness {
self.psess.gated_spans.gate(sym::const_trait_impl, span);
}
let safety = self.parse_safety(Case::Sensitive);
// Parse optional `auto` prefix.
let is_auto = if self.eat_keyword(exp!(Auto)) {

View file

@ -17,11 +17,11 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType};
use crate::ast::{PatKind, TyKind};
use crate::errors::{
self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams,
PathSingleColon, PathTripleColon,
self, AttributeOnEmptyType, AttributeOnGenericArg, FnPathFoundNamedParams,
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
};
use crate::exp;
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
use crate::parser::{CommaRecoveryMode, ExprKind, RecoverColon, RecoverComma};
/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
@ -880,6 +880,12 @@ impl<'a> Parser<'a> {
&mut self,
ty_generics: Option<&Generics>,
) -> PResult<'a, Option<GenericArg>> {
let mut attr_span: Option<Span> = None;
if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
let attrs_wrapper = self.parse_outer_attributes()?;
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
attr_span = Some(raw_attrs[0].span.to(raw_attrs.last().unwrap().span));
}
let start = self.token.span;
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
// Parse lifetime argument.
@ -934,6 +940,9 @@ impl<'a> Parser<'a> {
}
} else if self.token.is_keyword(kw::Const) {
return self.recover_const_param_declaration(ty_generics);
} else if let Some(attr_span) = attr_span {
let diag = self.dcx().create_err(AttributeOnEmptyType { span: attr_span });
return Err(diag);
} else {
// Fall back by trying to parse a const-expr expression. If we successfully do so,
// then we should report an error that it needs to be wrapped in braces.
@ -953,6 +962,22 @@ impl<'a> Parser<'a> {
}
}
};
if let Some(attr_span) = attr_span {
let guar = self.dcx().emit_err(AttributeOnGenericArg {
span: attr_span,
fix_span: attr_span.until(arg.span()),
});
return Ok(Some(match arg {
GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))),
GenericArg::Const(_) => {
let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar));
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr })
}
GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt),
}));
}
Ok(Some(arg))
}

View file

@ -14,10 +14,10 @@ use thin_vec::{ThinVec, thin_vec};
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
use crate::errors::{
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidDynKeyword,
LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
ReturnTypesUseThinArrow,
self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
NestedCVariadicType, ReturnTypesUseThinArrow,
};
use crate::parser::item::FrontMatterParsingMode;
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
@ -253,7 +253,27 @@ impl<'a> Parser<'a> {
) -> PResult<'a, P<Ty>> {
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
let attrs_wrapper = self.parse_outer_attributes()?;
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
let (full_span, guar) = match self.parse_ty() {
Ok(ty) => {
let full_span = attr_span.until(ty.span);
let guar = self
.dcx()
.emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
(attr_span, guar)
}
Err(err) => {
err.cancel();
let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
(attr_span, guar)
}
};
return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
}
if let Some(ty) = self.eat_metavar_seq_with_matcher(
|mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
|this| this.parse_ty_no_question_mark_recover(),

View file

@ -324,6 +324,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => {
self.check_coverage(attr_span, span, target)
}
&Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
self.check_coroutine(attr_span, target)
}
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
@ -390,9 +393,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
[sym::coroutine, ..] => {
self.check_coroutine(attr, target);
}
[sym::linkage, ..] => self.check_linkage(attr, span, target),
[
// ok
@ -2651,11 +2651,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_coroutine(&self, attr: &Attribute, target: Target) {
fn check_coroutine(&self, attr_span: Span, target: Target) {
match target {
Target::Closure => return,
_ => {
self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span() });
self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr_span });
}
}
}

View file

@ -1111,6 +1111,11 @@ impl File {
/// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this
/// [may change in the future][changes].
///
/// On most platforms, including UNIX and Windows platforms, this function can also change the
/// timestamps of a directory. To get a `File` representing a directory in order to call
/// `set_times`, open the directory with `File::open` without attempting to obtain write
/// permission.
///
/// [changes]: io#platform-specific-behavior
///
/// # Errors
@ -1128,7 +1133,7 @@ impl File {
/// use std::fs::{self, File, FileTimes};
///
/// let src = fs::metadata("src")?;
/// let dest = File::options().write(true).open("dest")?;
/// let dest = File::open("dest")?;
/// let times = FileTimes::new()
/// .set_accessed(src.accessed()?)
/// .set_modified(src.modified()?);

View file

@ -108,8 +108,6 @@ impl<'a> PanicHookInfo<'a> {
/// # Example
///
/// ```should_panic
/// #![feature(panic_payload_as_str)]
///
/// std::panic::set_hook(Box::new(|panic_info| {
/// if let Some(s) = panic_info.payload_as_str() {
/// println!("panic occurred: {s:?}");
@ -122,7 +120,7 @@ impl<'a> PanicHookInfo<'a> {
/// ```
#[must_use]
#[inline]
#[unstable(feature = "panic_payload_as_str", issue = "125175")]
#[stable(feature = "panic_payload_as_str", since = "CURRENT_RUSTC_VERSION")]
pub fn payload_as_str(&self) -> Option<&str> {
if let Some(s) = self.payload.downcast_ref::<&str>() {
Some(s)

View file

@ -2683,6 +2683,8 @@ impl Path {
///
/// assert_eq!("foo", Path::new("foo.rs").file_prefix().unwrap());
/// assert_eq!("foo", Path::new("foo.tar.gz").file_prefix().unwrap());
/// assert_eq!(".config", Path::new(".config").file_prefix().unwrap());
/// assert_eq!(".config", Path::new(".config.toml").file_prefix().unwrap());
/// ```
///
/// # See Also

View file

@ -84,7 +84,7 @@ impl Step for Std {
Kind::Check,
);
std_cargo(builder, target, stage, &mut cargo);
std_cargo(builder, target, &mut cargo);
if matches!(builder.config.cmd, Subcommand::Fix) {
// By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
cargo.arg("--lib");
@ -125,7 +125,7 @@ impl Step for Std {
Kind::Check,
);
std_cargo(builder, target, build_compiler.stage, &mut cargo);
std_cargo(builder, target, &mut cargo);
// Explicitly pass -p for all dependencies krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather

View file

@ -154,7 +154,7 @@ impl Step for Std {
Kind::Clippy,
);
std_cargo(builder, target, compiler.stage, &mut cargo);
std_cargo(builder, target, &mut cargo);
for krate in &*self.crates {
cargo.arg("-p").arg(krate);

View file

@ -269,7 +269,7 @@ impl Step for Std {
target,
Kind::Build,
);
std_cargo(builder, target, compiler.stage, &mut cargo);
std_cargo(builder, target, &mut cargo);
for krate in &*self.crates {
cargo.arg("-p").arg(krate);
}
@ -497,7 +497,7 @@ fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
/// Configure cargo to compile the standard library, adding appropriate env vars
/// and such.
pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
// rustc already ensures that it builds with the minimum deployment
// target, so ideally we shouldn't need to do anything here.
//
@ -645,12 +645,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// built with bitcode so that the produced rlibs can be used for both LTO
// builds (which use bitcode) and non-LTO builds (which use object code).
// So we override the override here!
//
// But we don't bother for the stage 0 compiler because it's never used
// with LTO.
if stage >= 1 {
cargo.rustflag("-Cembed-bitcode=yes");
}
cargo.rustflag("-Cembed-bitcode=yes");
if builder.config.rust_lto == RustcLto::Off {
cargo.rustflag("-Clto=off");
}

View file

@ -722,7 +722,7 @@ fn doc_std(
let mut cargo =
builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, Kind::Doc);
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
compile::std_cargo(builder, target, &mut cargo);
cargo
.arg("--no-deps")
.arg("--target-dir")

View file

@ -2858,7 +2858,7 @@ impl Step for Crate {
.arg("--manifest-path")
.arg(builder.src.join("library/sysroot/Cargo.toml"));
} else {
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
compile::std_cargo(builder, target, &mut cargo);
}
}
Mode::Rustc => {

View file

@ -480,10 +480,28 @@ impl Item {
}
}
/// If the item has doc comments from a reexport, returns the item id of that reexport,
/// otherwise returns returns the item id.
///
/// This is used as a key for caching intra-doc link resolution,
/// to prevent two reexports of the same item from using the same cache.
pub(crate) fn item_or_reexport_id(&self) -> ItemId {
// added documentation on a reexport is always prepended.
self.attrs
.doc_strings
.first()
.map(|x| x.item_id)
.flatten()
.map(ItemId::from)
.unwrap_or(self.item_id)
}
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
use crate::html::format::{href, link_tooltip};
let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
return vec![];
};
links
.iter()
.filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {

View file

@ -804,8 +804,7 @@ impl Options {
let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
let with_examples = matches.opt_strs("with-examples");
let call_locations =
crate::scrape_examples::load_call_locations(with_examples, dcx, &mut loaded_paths);
let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
let doctest_build_args = matches.opt_strs("doctest-build-arg");
let unstable_features =

View file

@ -1082,7 +1082,12 @@ impl LinkCollector<'_, '_> {
for md_link in preprocessed_markdown_links(&doc) {
let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
if let Some(link) = link {
self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
self.cx
.cache
.intra_doc_links
.entry(item.item_or_reexport_id())
.or_default()
.insert(link);
}
}
}

View file

@ -333,11 +333,14 @@ pub(crate) fn run(
pub(crate) fn load_call_locations(
with_examples: Vec<String>,
dcx: DiagCtxtHandle<'_>,
loaded_paths: &mut Vec<PathBuf>,
) -> AllCallLocations {
let mut all_calls: AllCallLocations = FxIndexMap::default();
for path in with_examples {
loaded_paths.push(path.clone().into());
// FIXME: Figure out why this line is causing this feature to crash in specific contexts.
// Full issue backlog is available here: <https://github.com/rust-lang/rust/pull/144600>.
//
// Can be checked with `tests/run-make/rustdoc-scrape-examples-paths`.
// loaded_paths.push(path.clone().into());
let bytes = match fs::read(&path) {
Ok(bytes) => bytes,
Err(e) => dcx.fatal(format!("failed to load examples: {e}")),

View file

@ -0,0 +1,8 @@
[package]
name = "foo"
version = "0.0.1"
edition = "2024"
[[example]]
name = "complex"
doc-scrape-examples = true

View file

@ -0,0 +1,3 @@
fn main() {
let mut x = foo::X::new();
}

View file

@ -0,0 +1 @@
// This file MUST exist to trigger the original bug.

View file

@ -0,0 +1,7 @@
pub struct X;
impl X {
pub fn new() -> Self {
X
}
}

View file

@ -0,0 +1,16 @@
//! Test to ensure that the rustdoc `scrape-examples` feature is not panicking.
//! Regression test for <https://github.com/rust-lang/rust/issues/144752>.
use run_make_support::{cargo, path, rfs};
fn main() {
// We copy the crate to be documented "outside" to prevent documenting
// the whole compiler.
let tmp = std::env::temp_dir();
let test_crate = tmp.join("foo");
rfs::copy_dir_all(path("foo"), &test_crate);
// The `scrape-examples` feature is also implemented in `cargo` so instead of reproducing
// what `cargo` does, better to just let `cargo` do it.
cargo().current_dir(&test_crate).args(["doc", "-p", "foo", "-Zrustdoc-scrape-examples"]).run();
}

View file

@ -0,0 +1,35 @@
// regression test for https://github.com/rust-lang/rust/issues/144965
#![crate_name = "foo"]
#![no_std]
#[doc(hidden)]
pub struct MyStruct;
macro_rules! my_macro {
() => {
pub fn my_function() {}
/// Incorrect: [`my_function()`].
#[doc(inline)]
pub use $crate::MyStruct;
/// Correct: [`my_function`].
pub struct AnotherStruct;
};
}
pub mod one {
//@ has 'foo/one/index.html'
//@ has - '//dl[@class="item-table"]/dd[1]/a[@href="fn.my_function.html"]/code' 'my_function'
//@ has - '//dl[@class="item-table"]/dd[2]/a[@href="fn.my_function.html"]/code' 'my_function()'
my_macro!();
}
pub mod two {
//@ has 'foo/two/index.html'
//@ has - '//dl[@class="item-table"]/dd[1]/a[@href="fn.my_function.html"]/code' 'my_function'
//@ has - '//dl[@class="item-table"]/dd[2]/a[@href="fn.my_function.html"]/code' 'my_function()'
my_macro!();
}

View file

@ -55,12 +55,6 @@ error: malformed `patchable_function_entry` attribute input
LL | #[patchable_function_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
error: malformed `coroutine` attribute input
--> $DIR/malformed-attrs.rs:108:5
|
LL | #[coroutine = 63] || {}
| ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]`
error: malformed `must_not_suspend` attribute input
--> $DIR/malformed-attrs.rs:129:1
|
@ -436,6 +430,15 @@ LL | #[proc_macro = 18]
| | didn't expect any arguments here
| help: must be of the form: `#[proc_macro]`
error[E0565]: malformed `coroutine` attribute input
--> $DIR/malformed-attrs.rs:108:5
|
LL | #[coroutine = 63] || {}
| ^^^^^^^^^^^^----^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[coroutine]`
error[E0565]: malformed `proc_macro_attribute` attribute input
--> $DIR/malformed-attrs.rs:113:1
|

View file

@ -1,6 +1,6 @@
struct Foo<const N: usize>;
impl<const N: usize = 1> Foo<N> {}
//~^ ERROR defaults for const parameters are only allowed
//~^ ERROR defaults for generic parameters are not allowed here
fn main() {}

View file

@ -1,4 +1,4 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/default-on-impl.rs:3:6
|
LL | impl<const N: usize = 1> Foo<N> {}

View file

@ -1,10 +1,10 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
#![expect(incomplete_features)]
trait Trait<T> {
fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for generic parameters are not allowed here
//~^ ERROR: mismatched types
fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for generic parameters are not allowed here
}
fn main() {}

View file

@ -1,10 +1,10 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/issue-105257.rs:5:12
|
LL | fn fnc<const N: usize = "">(&self) {}
| ^^^^^^^^^^^^^^^^^^^
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/issue-105257.rs:7:12
|
LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {}

View file

@ -1,4 +1,4 @@
#![crate_type = "lib"]
fn foo<const SIZE: usize = 5usize>() {}
//~^ ERROR defaults for const parameters are
//~^ ERROR defaults for generic parameters are not allowed here

View file

@ -1,4 +1,4 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/default_function_param.rs:3:8
|
LL | fn foo<const SIZE: usize = 5usize>() {}

View file

@ -0,0 +1,13 @@
// Regression test for <https://github.com/rust-lang/rust/issues/144826>.
//@ check-pass
#![feature(explicit_tail_calls)]
#![expect(incomplete_features)]
fn foo(x: fn(&i32)) {
become bar(x);
}
fn bar(_: fn(&i32)) {}
fn main() {}

View file

@ -0,0 +1,16 @@
#![feature(explicit_tail_calls)]
#![expect(incomplete_features)]
fn link(x: &str) -> &'static str {
become passthrough(x);
//~^ ERROR lifetime may not live long enough
}
fn passthrough<T>(t: T) -> T { t }
fn main() {
let x = String::from("hello, world");
let s = link(&x);
drop(x);
println!("{s}");
}

View file

@ -0,0 +1,10 @@
error: lifetime may not live long enough
--> $DIR/ret-ty-borrowck-constraints.rs:5:5
|
LL | fn link(x: &str) -> &'static str {
| - let's call the lifetime of this reference `'1`
LL | become passthrough(x);
| ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
error: aborting due to 1 previous error

View file

@ -4,17 +4,17 @@
trait Trait {
type Assoc<T = u32>;
//~^ ERROR defaults for type parameters are only allowed
//~^ ERROR defaults for generic parameters are not allowed here
}
impl Trait for () {
type Assoc<T = u32> = u64;
//~^ ERROR defaults for type parameters are only allowed
//~^ ERROR defaults for generic parameters are not allowed here
}
impl Trait for u32 {
type Assoc<T = u32> = T;
//~^ ERROR defaults for type parameters are only allowed
//~^ ERROR defaults for generic parameters are not allowed here
}
trait Other {}

View file

@ -1,16 +1,16 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:6:16
|
LL | type Assoc<T = u32>;
| ^^^^^^^
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:11:16
|
LL | type Assoc<T = u32> = u64;
| ^^^^^^^
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:16:16
|
LL | type Assoc<T = u32> = T;

View file

@ -7,9 +7,17 @@
// FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly.
const NONE<T = ()>: Option<T> = None::<T>; //~ ERROR defaults for type parameters are only allowed
const NONE<T = ()>: Option<T> = None::<T>;
//~^ ERROR defaults for generic parameters are not allowed here
fn main() {
let _ = NONE;
//~^ ERROR type annotations needed
impl Host {
const NADA<T = ()>: Option<T> = None::<T>;
//~^ ERROR defaults for generic parameters are not allowed here
}
enum Host {}
fn body0() { let _ = NONE; } //~ ERROR type annotations needed
fn body1() { let _ = Host::NADA; } //~ ERROR type annotations needed
fn main() {}

View file

@ -1,20 +1,37 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/parameter-defaults.rs:10:12
|
LL | const NONE<T = ()>: Option<T> = None::<T>;
| ^^^^^^
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:13:9
error: defaults for generic parameters are not allowed here
--> $DIR/parameter-defaults.rs:14:16
|
LL | let _ = NONE;
| ^ ---- type must be known at this point
LL | const NADA<T = ()>: Option<T> = None::<T>;
| ^^^^^^
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:20:18
|
LL | fn body0() { let _ = NONE; }
| ^ ---- type must be known at this point
|
help: consider giving this pattern a type, where the type for type parameter `T` is specified
|
LL | let _: Option<T> = NONE;
| +++++++++++
LL | fn body0() { let _: Option<T> = NONE; }
| +++++++++++
error: aborting due to 2 previous errors
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:21:18
|
LL | fn body1() { let _ = Host::NADA; }
| ^ ---------- type must be known at this point
|
help: consider giving this pattern a type, where the type for type parameter `T` is specified
|
LL | fn body1() { let _: Option<T> = Host::NADA; }
| +++++++++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0282`.

View file

@ -1,7 +1,15 @@
// Ensure that we reject generic parameters on foreign items.
extern "C" {
fn foo<T>(); //~ ERROR foreign items may not have type parameters
// Furthermore, check that type parameter defaults lead to a *hard* error,
// not just a lint error, for maximum forward compatibility.
#[allow(invalid_type_param_default)] // Should have no effect here.
fn bar<T = ()>(); //~ ERROR foreign items may not have type parameters
//~^ ERROR defaults for generic parameters are not allowed here
}
fn main() {
foo::<i32>(); //~ ERROR requires unsafe
unsafe { foo::<i32>() };
}

View file

@ -1,20 +1,25 @@
error[E0044]: foreign items may not have type parameters
--> $DIR/generic-extern.rs:2:5
--> $DIR/generic-extern.rs:4:5
|
LL | fn foo<T>();
| ^^^^^^^^^^^^ can't have type parameters
|
= help: replace the type parameters with concrete types like `u32`
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
--> $DIR/generic-extern.rs:6:5
error: defaults for generic parameters are not allowed here
--> $DIR/generic-extern.rs:9:12
|
LL | foo::<i32>();
| ^^^^^^^^^^^^ call to unsafe function
LL | fn bar<T = ()>();
| ^^^^^^
error[E0044]: foreign items may not have type parameters
--> $DIR/generic-extern.rs:9:5
|
= note: consult the function's documentation for information on how to avoid undefined behavior
LL | fn bar<T = ()>();
| ^^^^^^^^^^^^^^^^^ can't have type parameters
|
= help: replace the type parameters with concrete types like `u32`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0044, E0133.
For more information about an error, try `rustc --explain E0044`.
For more information about this error, try `rustc --explain E0044`.

View file

@ -0,0 +1,22 @@
// Ensure that we emit the deny-by-default lint `invalid_type_param_default` in locations where
// type parameter defaults were accidentally allowed but don't have any effect whatsoever.
//
// Tracked in <https://github.com/rust-lang/rust/issues/36887>.
// FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly.
fn avg<T = i32>(_: T) {}
//~^ ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
// issue: <https://github.com/rust-lang/rust/issues/26812>
fn mdn<T = T::Item>(_: T) {}
//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
//~| ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
struct S<T>(T);
impl<T = i32> S<T> {}
//~^ ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
fn main() {}

View file

@ -0,0 +1,70 @@
error[E0128]: generic parameter defaults cannot reference parameters before they are declared
--> $DIR/invalid-type-param-default.rs:12:12
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^ cannot reference `T` before it is declared
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:7:8
|
LL | fn avg<T = i32>(_: T) {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:12:8
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:18:6
|
LL | impl<T = i32> S<T> {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0128`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:7:8
|
LL | fn avg<T = i32>(_: T) {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:12:8
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:18:6
|
LL | impl<T = i32> S<T> {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View file

@ -1,7 +1,7 @@
fn mainIterator<_ = _> {}
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR missing parameters for function definition
//~| ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions [invalid_type_param_default]
//~| ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121]

View file

@ -15,7 +15,7 @@ help: add a parameter list
LL | fn mainIterator<_ = _>() {}
| ++
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/overlapping-errors-span-issue-123861.rs:1:17
|
LL | fn mainIterator<_ = _> {}
@ -35,7 +35,7 @@ error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0121`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/overlapping-errors-span-issue-123861.rs:1:17
|
LL | fn mainIterator<_ = _> {}

View file

@ -236,17 +236,15 @@ type InTypeAliasGenericParamDefault<T = impl Debug> = T;
//~^ ERROR `impl Trait` is not allowed in generic parameter defaults
// Disallowed
impl <T = impl Debug> T {}
//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
//~| WARNING this was previously accepted by the compiler but is being phased out
//~| ERROR `impl Trait` is not allowed in generic parameter defaults
#[expect(invalid_type_param_default)]
impl<T = impl Debug> T {}
//~^ ERROR `impl Trait` is not allowed in generic parameter defaults
//~| ERROR no nominal type found
// Disallowed
#[expect(invalid_type_param_default)]
fn in_method_generic_param_default<T = impl Debug>(_: T) {}
//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
//~| WARNING this was previously accepted by the compiler but is being phased out
//~| ERROR `impl Trait` is not allowed in generic parameter defaults
//~^ ERROR `impl Trait` is not allowed in generic parameter defaults
fn main() {
let _in_local_variable: impl Fn() = || {};

View file

@ -311,10 +311,10 @@ LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in generic parameter defaults
--> $DIR/where-allowed.rs:239:11
--> $DIR/where-allowed.rs:240:10
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^
LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
@ -327,7 +327,7 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
--> $DIR/where-allowed.rs:252:29
--> $DIR/where-allowed.rs:250:29
|
LL | let _in_local_variable: impl Fn() = || {};
| ^^^^^^^^^
@ -338,7 +338,7 @@ LL | let _in_local_variable: impl Fn() = || {};
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0562]: `impl Trait` is not allowed in closure return types
--> $DIR/where-allowed.rs:254:46
--> $DIR/where-allowed.rs:252:46
|
LL | let _in_return_in_local_variable = || -> impl Fn() { || {} };
| ^^^^^^^^^
@ -368,25 +368,6 @@ LL - fn in_trait_impl_return() -> impl Debug { () }
LL + fn in_trait_impl_return() -> <() as DummyTrait>::Out { () }
|
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:246:36
|
LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:239:7
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error[E0283]: type annotations needed
--> $DIR/where-allowed.rs:46:57
|
@ -408,10 +389,10 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
error[E0118]: no nominal type found for inherent implementation
--> $DIR/where-allowed.rs:239:1
--> $DIR/where-allowed.rs:240:1
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
@ -431,29 +412,21 @@ LL | type InTypeAlias<R> = impl Debug;
|
= note: `InTypeAlias` must be used in combination with a concrete type within the same crate
error: aborting due to 50 previous errors
error: aborting due to 48 previous errors
Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666.
For more information about an error, try `rustc --explain E0053`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
warning: defaults for generic parameters are not allowed here
--> $DIR/where-allowed.rs:246:36
|
LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:239:7
warning: defaults for generic parameters are not allowed here
--> $DIR/where-allowed.rs:240:6
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^

View file

@ -1,6 +0,0 @@
fn avg<T=T::Item>(_: T) {}
//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
//~| ERROR defaults for type parameters
//~| WARN previously accepted
fn main() {}

View file

@ -1,30 +0,0 @@
error[E0128]: generic parameter defaults cannot reference parameters before they are declared
--> $DIR/issue-26812.rs:1:10
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^ cannot reference `T` before it is declared
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/issue-26812.rs:1:8
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0128`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/issue-26812.rs:1:8
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View file

@ -14,7 +14,7 @@ fn b<const C: u8()>() {}
// Paren generic args in AnonymousReportError
fn c<T = u8()>() {}
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| ERROR defaults for type parameters are only allowed in
//~| ERROR defaults for generic parameters are not allowed here
//~| WARN this was previously accepted
// Elided lifetime in path in ConstGeneric

View file

@ -22,7 +22,7 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
LL | fn c<T = u8()>() {}
| ^^^^ only `Fn` traits may use parentheses
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/unusual-rib-combinations.rs:15:6
|
LL | fn c<T = u8()>() {}
@ -43,7 +43,7 @@ error: aborting due to 6 previous errors
Some errors have detailed explanations: E0106, E0214, E0308, E0770.
For more information about an error, try `rustc --explain E0106`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/unusual-rib-combinations.rs:15:6
|
LL | fn c<T = u8()>() {}

View file

@ -5,7 +5,7 @@ impl X<N> {}
//~| ERROR unresolved item provided when a constant was expected
impl<T, const A: u8 = 2> X<N> {}
//~^ ERROR cannot find type `N` in this scope
//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
//~| ERROR defaults for generic parameters are not allowed here
//~| ERROR unresolved item provided when a constant was expected
fn foo(_: T) where T: Send {}

View file

@ -103,7 +103,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | impl X<{ N }> {}
| + +
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/missing-type-parameter2.rs:6:9
|
LL | impl<T, const A: u8 = 2> X<N> {}

View file

@ -0,0 +1,29 @@
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
//! <https://github.com/rust-lang/rust/issues/135017>
struct Baz<const N: usize>(i32);
fn main() {
let _: Baz<#[cfg(any())]> = todo!();
//~^ ERROR attributes cannot be applied here
}
fn f(_param: #[attr]) {}
//~^ ERROR attributes cannot be applied to a function parameter's type
//~| ERROR expected type, found `)`
fn g() -> #[attr] { 0 }
//~^ ERROR attributes cannot be applied here
struct S {
field: #[attr],
//~^ ERROR attributes cannot be applied here
field1: (#[attr], i32),
//~^ ERROR attributes cannot be applied here
}
type Tuple = (#[attr], String);
//~^ ERROR attributes cannot be applied here
impl #[attr] {}
//~^ ERROR attributes cannot be applied here

View file

@ -0,0 +1,52 @@
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:7:16
|
LL | let _: Baz<#[cfg(any())]> = todo!();
| - ^^^^^^^^^^^^^ attributes are not allowed here
| |
| while parsing the type for `_`
error: attributes cannot be applied to a function parameter's type
--> $DIR/attribute-on-empty.rs:11:14
|
LL | fn f(_param: #[attr]) {}
| ^^^^^^^ attributes are not allowed here
error: expected type, found `)`
--> $DIR/attribute-on-empty.rs:11:21
|
LL | fn f(_param: #[attr]) {}
| ^ expected type
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:15:11
|
LL | fn g() -> #[attr] { 0 }
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:19:12
|
LL | field: #[attr],
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:21:14
|
LL | field1: (#[attr], i32),
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:25:15
|
LL | type Tuple = (#[attr], String);
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied here
--> $DIR/attribute-on-empty.rs:28:6
|
LL | impl #[attr] {}
| ^^^^^^^ attributes are not allowed here
error: aborting due to 8 previous errors

View file

@ -0,0 +1,58 @@
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
//! <https://github.com/rust-lang/rust/issues/135017>
//@ run-rustfix
#![allow(dead_code, unused_variables)]
struct Foo<T>(T);
struct Bar<'a>(&'a i32);
struct Baz<const N: usize>(i32);
fn main() {
let foo: Foo<i32> = Foo(2i32);
//~^ ERROR attributes cannot be applied to generic arguments
let _: &'static str = "123";
//~^ ERROR attributes cannot be applied to types
let _: Bar<'static> = Bar(&123);
//~^ ERROR attributes cannot be applied to generic arguments
let _: Baz<42> = Baz(42);
//~^ ERROR attributes cannot be applied to generic arguments
let _: Foo<String> = Foo(String::new());
//~^ ERROR attributes cannot be applied to generic arguments
let _: Bar<'static> = Bar(&456);
//~^ ERROR attributes cannot be applied to generic arguments
let _generic: Box<i32> = Box::new(1);
//~^ ERROR attributes cannot be applied to generic arguments
let _assignment: i32 = *Box::new(1);
//~^ ERROR attributes cannot be applied to types
let _complex: Vec<String> = vec![];
//~^ ERROR attributes cannot be applied to generic arguments
let _nested: Box<Vec<u64>> = Box::new(vec![]);
//~^ ERROR attributes cannot be applied to generic arguments
}
fn g() -> i32 { 0 }
//~^ ERROR attributes cannot be applied to types
struct S {
field: i32,
//~^ ERROR attributes cannot be applied to types
field1: (i32, i32),
//~^ ERROR attributes cannot be applied to types
}
type Tuple = (i32, String);
//~^ ERROR attributes cannot be applied to types
impl S {}
//~^ ERROR attributes cannot be applied to types

View file

@ -0,0 +1,58 @@
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
//! <https://github.com/rust-lang/rust/issues/135017>
//@ run-rustfix
#![allow(dead_code, unused_variables)]
struct Foo<T>(T);
struct Bar<'a>(&'a i32);
struct Baz<const N: usize>(i32);
fn main() {
let foo: Foo<#[cfg(not(wrong))] i32> = Foo(2i32);
//~^ ERROR attributes cannot be applied to generic arguments
let _: #[attr] &'static str = "123";
//~^ ERROR attributes cannot be applied to types
let _: Bar<#[cfg(any())] 'static> = Bar(&123);
//~^ ERROR attributes cannot be applied to generic arguments
let _: Baz<#[cfg(any())] 42> = Baz(42);
//~^ ERROR attributes cannot be applied to generic arguments
let _: Foo<#[cfg(not(wrong))]String> = Foo(String::new());
//~^ ERROR attributes cannot be applied to generic arguments
let _: Bar<#[cfg(any())] 'static> = Bar(&456);
//~^ ERROR attributes cannot be applied to generic arguments
let _generic: Box<#[attr] i32> = Box::new(1);
//~^ ERROR attributes cannot be applied to generic arguments
let _assignment: #[attr] i32 = *Box::new(1);
//~^ ERROR attributes cannot be applied to types
let _complex: Vec<#[derive(Debug)] String> = vec![];
//~^ ERROR attributes cannot be applied to generic arguments
let _nested: Box<Vec<#[cfg(feature = "test")] u64>> = Box::new(vec![]);
//~^ ERROR attributes cannot be applied to generic arguments
}
fn g() -> #[attr] i32 { 0 }
//~^ ERROR attributes cannot be applied to types
struct S {
field: #[attr] i32,
//~^ ERROR attributes cannot be applied to types
field1: (#[attr] i32, i32),
//~^ ERROR attributes cannot be applied to types
}
type Tuple = (#[attr] i32, String);
//~^ ERROR attributes cannot be applied to types
impl #[attr] S {}
//~^ ERROR attributes cannot be applied to types

View file

@ -0,0 +1,92 @@
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:13:18
|
LL | let foo: Foo<#[cfg(not(wrong))] i32> = Foo(2i32);
| ^^^^^^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:16:12
|
LL | let _: #[attr] &'static str = "123";
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:19:16
|
LL | let _: Bar<#[cfg(any())] 'static> = Bar(&123);
| ^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:22:16
|
LL | let _: Baz<#[cfg(any())] 42> = Baz(42);
| ^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:25:16
|
LL | let _: Foo<#[cfg(not(wrong))]String> = Foo(String::new());
| ^^^^^^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:28:16
|
LL | let _: Bar<#[cfg(any())] 'static> = Bar(&456);
| ^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:31:23
|
LL | let _generic: Box<#[attr] i32> = Box::new(1);
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:34:22
|
LL | let _assignment: #[attr] i32 = *Box::new(1);
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:37:23
|
LL | let _complex: Vec<#[derive(Debug)] String> = vec![];
| ^^^^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to generic arguments
--> $DIR/attribute-on-type.rs:40:26
|
LL | let _nested: Box<Vec<#[cfg(feature = "test")] u64>> = Box::new(vec![]);
| ^^^^^^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:44:11
|
LL | fn g() -> #[attr] i32 { 0 }
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:48:12
|
LL | field: #[attr] i32,
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:50:14
|
LL | field1: (#[attr] i32, i32),
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:54:15
|
LL | type Tuple = (#[attr] i32, String);
| ^^^^^^^ attributes are not allowed here
error: attributes cannot be applied to types
--> $DIR/attribute-on-type.rs:57:6
|
LL | impl #[attr] S {}
| ^^^^^^^ attributes are not allowed here
error: aborting due to 15 previous errors

View file

@ -1,5 +1,5 @@
fn main() {
x::<#[a]y::<z>>
//~^ ERROR invalid const generic expression
//~^ ERROR attributes cannot be applied to generic arguments
//~| ERROR cannot find value `x` in this scope
}

View file

@ -1,13 +1,8 @@
error: invalid const generic expression
--> $DIR/issue-103143.rs:2:13
error: attributes cannot be applied to generic arguments
--> $DIR/issue-103143.rs:2:9
|
LL | x::<#[a]y::<z>>
| ^^^^^^
|
help: expressions must be enclosed in braces to be used as const generic arguments
|
LL | x::<#[a]{ y::<z> }>
| + +
| ^^^^ attributes are not allowed here
error[E0425]: cannot find value `x` in this scope
--> $DIR/issue-103143.rs:2:5

View file

@ -1,7 +1,9 @@
// Regression test for issues #100790 and #106439.
//@ run-rustfix
pub struct Example(#[allow(dead_code)] usize)
#![allow(dead_code)]
pub struct Example(usize)
where
(): Sized;
//~^^^ ERROR where clauses are not allowed before tuple struct bodies

View file

@ -1,10 +1,12 @@
// Regression test for issues #100790 and #106439.
//@ run-rustfix
#![allow(dead_code)]
pub struct Example
where
(): Sized,
(#[allow(dead_code)] usize);
(usize);
//~^^^ ERROR where clauses are not allowed before tuple struct bodies
struct _Demo

View file

@ -1,23 +1,23 @@
error: where clauses are not allowed before tuple struct bodies
--> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1
--> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:7:1
|
LL | pub struct Example
| ------- while parsing this tuple struct
LL | / where
LL | | (): Sized,
| |______________^ unexpected where clause
LL | (#[allow(dead_code)] usize);
| --------------------------- the struct body
LL | (usize);
| ------- the struct body
|
help: move the body before the where clause
|
LL ~ pub struct Example(#[allow(dead_code)] usize)
LL ~ pub struct Example(usize)
LL | where
LL ~ (): Sized;
|
error: where clauses are not allowed before tuple struct bodies
--> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1
--> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:13:1
|
LL | struct _Demo
| ----- while parsing this tuple struct

View file

@ -13,6 +13,9 @@ impl const T for S {}
const fn f<A: [const] T>() {} //[stock]~ ERROR const trait impls are experimental
fn g<A: const T>() {} //[stock]~ ERROR const trait impls are experimental
const trait Trait {} //[stock]~ ERROR const trait impls are experimental
#[cfg(false)] const trait Trait {} //[stock]~ ERROR const trait impls are experimental
macro_rules! discard { ($ty:ty) => {} }
discard! { impl [const] T } //[stock]~ ERROR const trait impls are experimental

View file

@ -29,7 +29,27 @@ LL | fn g<A: const T>() {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: const trait impls are experimental
--> $DIR/feature-gate.rs:18:17
--> $DIR/feature-gate.rs:16:1
|
LL | const trait Trait {}
| ^^^^^
|
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: const trait impls are experimental
--> $DIR/feature-gate.rs:17:15
|
LL | #[cfg(false)] const trait Trait {}
| ^^^^^
|
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: const trait impls are experimental
--> $DIR/feature-gate.rs:21:17
|
LL | discard! { impl [const] T }
| ^^^^^^^
@ -39,7 +59,7 @@ LL | discard! { impl [const] T }
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: const trait impls are experimental
--> $DIR/feature-gate.rs:19:17
--> $DIR/feature-gate.rs:22:17
|
LL | discard! { impl const T }
| ^^^^^
@ -58,6 +78,6 @@ LL | #[const_trait]
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 6 previous errors
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -13,7 +13,7 @@ error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.
Future incompatibility report: Future breakage diagnostic:
warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
warning: defaults for generic parameters are not allowed here
--> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11
|
LL | fn foo<T, U = u64>() -> (T, U) {

View file

@ -1,12 +0,0 @@
#![allow(unused)]
fn avg<T=i32>(_: T) {}
//~^ ERROR defaults for type parameters are only allowed
//~| WARN this was previously accepted
struct S<T>(T);
impl<T=i32> S<T> {}
//~^ ERROR defaults for type parameters are only allowed
//~| WARN this was previously accepted
fn main() {}

View file

@ -1,43 +0,0 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
|
LL | fn avg<T=i32>(_: T) {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
|
LL | impl<T=i32> S<T> {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: aborting due to 2 previous errors
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
|
LL | fn avg<T=i32>(_: T) {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
|
LL | impl<T=i32> S<T> {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View file

@ -4,7 +4,7 @@ trait Trait<const N: dyn Trait = bar> {
fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait {
//~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters
//~| ERROR expected value, found builtin type `u32`
//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
//~| ERROR defaults for generic parameters are not allowed here
bar
//~^ ERROR cannot find value `bar` in this scope
}

View file

@ -39,7 +39,7 @@ LL | trait Trait<const N: dyn Trait = bar> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
error: defaults for generic parameters are not allowed here
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:12
|
LL | fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait {