Merge pull request #4478 from rust-lang/rustup-2025-07-19
Automatic Rustup
This commit is contained in:
commit
eef454f89b
403 changed files with 8309 additions and 5211 deletions
|
|
@ -110,6 +110,22 @@ pub enum DeprecatedSince {
|
|||
Err,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Encodable,
|
||||
Decodable,
|
||||
Clone,
|
||||
HashStable_Generic,
|
||||
PrintAttribute
|
||||
)]
|
||||
pub enum CoverageStatus {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
/// Whether an item marked with #[deprecated(since = "X")] is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc
|
||||
|
|
@ -274,6 +290,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[const_trait]`.
|
||||
ConstTrait(Span),
|
||||
|
||||
/// Represents `#[coverage]`.
|
||||
Coverage(Span, CoverageStatus),
|
||||
|
||||
///Represents `#[rustc_deny_explicit_impl]`.
|
||||
DenyExplicitImpl(Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ impl AttributeKind {
|
|||
ConstStability { .. } => Yes,
|
||||
ConstStabilityIndirect => No,
|
||||
ConstTrait(..) => No,
|
||||
Coverage(..) => No,
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotImplementViaObject(..) => No,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_ast::token::CommentKind;
|
|||
use rustc_ast::{AttrStyle, IntTy, UintTy};
|
||||
use rustc_ast_pretty::pp::Printer;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
pub use stability::*;
|
||||
use thin_vec::ThinVec;
|
||||
pub use version::*;
|
||||
|
|
@ -170,7 +170,7 @@ macro_rules! print_tup {
|
|||
}
|
||||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, ());
|
||||
print_skip!(Span, (), ErrorGuaranteed);
|
||||
print_disp!(u16, bool, NonZero<u32>);
|
||||
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Symbol, sym};
|
||||
|
||||
use crate::{PrintAttribute, RustcVersion};
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ pub enum StableSince {
|
|||
/// Stabilized in the upcoming version, whatever number that is.
|
||||
Current,
|
||||
/// Failed to parse a stabilization version.
|
||||
Err,
|
||||
Err(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
impl StabilityLevel {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
|
||||
use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
|
@ -52,6 +52,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
|
||||
}
|
||||
|
||||
pub(crate) struct CoverageParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
|
||||
const PATH: &[Symbol] = &[sym::coverage];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(args) = args.list() else {
|
||||
cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(arg) = args.single() else {
|
||||
cx.expected_single_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]);
|
||||
|
||||
let Some(arg) = arg.meta_item() else {
|
||||
fail_incorrect_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let status = match arg.path().word_sym() {
|
||||
Some(sym::off) => CoverageStatus::Off,
|
||||
Some(sym::on) => CoverageStatus::On,
|
||||
None | Some(_) => {
|
||||
fail_incorrect_argument(arg.span());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some(AttributeKind::Coverage(cx.attr_span, status))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExportNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
||||
|
|
|
|||
|
|
@ -292,12 +292,12 @@ pub(crate) fn parse_stability<S: Stage>(
|
|||
} else if let Some(version) = parse_version(since) {
|
||||
StableSince::Version(version)
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
}
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
};
|
||||
|
||||
match feature {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ use crate::attributes::allow_unstable::{
|
|||
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
|
||||
};
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser,
|
||||
OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
|
||||
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
|
||||
OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
|
||||
UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
|
|
@ -139,6 +140,7 @@ attribute_parsers!(
|
|||
// tidy-alphabetical-end
|
||||
|
||||
// tidy-alphabetical-start
|
||||
Single<CoverageParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
|
|
@ -452,6 +454,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_specific_argument_and_list(
|
||||
&self,
|
||||
span: Span,
|
||||
possibilities: Vec<&'static str>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -469,6 +490,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: true,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,7 +533,9 @@ pub(crate) struct LinkOrdinalOutOfRange {
|
|||
|
||||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedNoArgs,
|
||||
ExpectedStringLiteral { byte_string: Option<Span> },
|
||||
ExpectedStringLiteral {
|
||||
byte_string: Option<Span>,
|
||||
},
|
||||
ExpectedIntegerLiteral,
|
||||
ExpectedAtLeastOneArgument,
|
||||
ExpectedSingleArgument,
|
||||
|
|
@ -541,7 +543,12 @@ pub(crate) enum AttributeParseErrorReason {
|
|||
UnexpectedLiteral,
|
||||
ExpectedNameValue(Option<Symbol>),
|
||||
DuplicateKey(Symbol),
|
||||
ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
|
||||
ExpectedSpecificArgument {
|
||||
possibilities: Vec<&'static str>,
|
||||
strings: bool,
|
||||
/// Should we tell the user to write a list when they didn't?
|
||||
list: bool,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) struct AttributeParseError {
|
||||
|
|
@ -615,7 +622,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
format!("expected this to be of the form `{name} = \"...\"`"),
|
||||
);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => {
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: false,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
|
|
@ -641,6 +652,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
}
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: true,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
&[x] => {
|
||||
diag.span_label(
|
||||
self.span,
|
||||
format!(
|
||||
"this attribute is only valid with {quote}{x}{quote} as an argument"
|
||||
),
|
||||
);
|
||||
}
|
||||
[first, second] => {
|
||||
diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
|
||||
}
|
||||
[first @ .., second_to_last, last] => {
|
||||
let mut res = String::new();
|
||||
for i in first {
|
||||
res.push_str(&format!("{quote}{i}{quote}, "));
|
||||
}
|
||||
res.push_str(&format!(
|
||||
"{quote}{second_to_last}{quote} or {quote}{last}{quote}"
|
||||
));
|
||||
|
||||
diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let suggestions = self.template.suggestions(false, &name);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
|
|
@ -7,7 +8,7 @@ use rustc_infer::infer::{InferCtxt, SubregionOrigin};
|
|||
use rustc_infer::traits::query::type_op::DeeplyNormalize;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
|
@ -70,10 +71,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
|
||||
let QueryRegionConstraints { outlives } = query_constraints;
|
||||
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
|
||||
let assumptions =
|
||||
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
|
||||
|
||||
for &(predicate, constraint_category) in outlives {
|
||||
self.convert(predicate, constraint_category);
|
||||
self.convert(predicate, constraint_category, &assumptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,15 +115,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
self.category = outlives_requirement.category;
|
||||
self.span = outlives_requirement.blame_span;
|
||||
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
|
||||
self.convert(
|
||||
ty::OutlivesPredicate(subject, outlived_region),
|
||||
self.category,
|
||||
&Default::default(),
|
||||
);
|
||||
}
|
||||
(self.category, self.span, self.from_closure) = backup;
|
||||
}
|
||||
|
||||
fn convert(
|
||||
&mut self,
|
||||
predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
predicate: ty::ArgOutlivesPredicate<'tcx>,
|
||||
constraint_category: ConstraintCategory<'tcx>,
|
||||
higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
|
|
@ -150,7 +158,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let mut next_outlives_predicates = vec![];
|
||||
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||
for (pred, constraint_category) in outlives_predicates {
|
||||
// Constraint is implied by a coroutine's well-formedness.
|
||||
if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
|
||||
&& higher_ranked_assumptions.contains(&pred)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = pred;
|
||||
match k1.kind() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
|
|
@ -266,14 +282,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
next_outlives_predicates: &mut Vec<(
|
||||
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
ty::ArgOutlivesPredicate<'tcx>,
|
||||
ConstraintCategory<'tcx>,
|
||||
)>,
|
||||
) -> Ty<'tcx> {
|
||||
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
|
||||
{
|
||||
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
|
||||
if let Some(QueryRegionConstraints { outlives }) = constraints {
|
||||
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
|
||||
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
|
||||
next_outlives_predicates.extend(outlives.iter().copied());
|
||||
}
|
||||
ty
|
||||
|
|
|
|||
|
|
@ -131,6 +131,11 @@ pub(crate) fn type_check<'tcx>(
|
|||
pre_obligations.is_empty(),
|
||||
"there should be no incoming region obligations = {pre_obligations:#?}",
|
||||
);
|
||||
let pre_assumptions = infcx.take_registered_region_assumptions();
|
||||
assert!(
|
||||
pre_assumptions.is_empty(),
|
||||
"there should be no incoming region assumptions = {pre_assumptions:#?}",
|
||||
);
|
||||
|
||||
debug!(?normalized_inputs_and_output);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_simple)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand_ext(cx, mitem, item, push, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const: false,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
structural_trait_def.expand(cx, mitem, item, push);
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods,
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
|
|||
methods: vec![partial_cmp_def],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,9 +181,11 @@ use std::{iter, vec};
|
|||
pub(crate) use StaticFields::*;
|
||||
pub(crate) use SubstructureFields::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
||||
Generics, Mutability, PatKind, VariantData,
|
||||
self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg,
|
||||
GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData,
|
||||
};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprPacked};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
|
|
@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> {
|
|||
pub associated_types: Vec<(Ident, Ty)>,
|
||||
|
||||
pub is_const: bool,
|
||||
|
||||
pub is_staged_api_crate: bool,
|
||||
}
|
||||
|
||||
pub(crate) struct MethodDef<'a> {
|
||||
|
|
@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> {
|
|||
// Create the type of `self`.
|
||||
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
||||
let self_type = cx.ty_path(path);
|
||||
let rustc_const_unstable =
|
||||
cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));
|
||||
|
||||
let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
|
||||
// Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd,
|
||||
// Other crates don't need stability attributes, so adding them is not useful, but libcore needs them
|
||||
// on all const trait impls.
|
||||
if self.is_const && self.is_staged_api_crate {
|
||||
attrs.push(
|
||||
cx.attr_nested(
|
||||
rustc_ast::AttrItem {
|
||||
unsafety: Safety::Default,
|
||||
path: rustc_const_unstable,
|
||||
args: AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(self.span),
|
||||
delim: rustc_ast::token::Delimiter::Parenthesis,
|
||||
tokens: [
|
||||
TokenKind::Ident(sym::feature, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const, None),
|
||||
TokenKind::Comma,
|
||||
TokenKind::Ident(sym::issue, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const_issue, None),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|kind| {
|
||||
TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone)
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
tokens: None,
|
||||
},
|
||||
self.span,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
|
||||
cx.item(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
|
|
|
|||
|
|
@ -530,8 +530,8 @@ fn codegen_cgu_content(
|
|||
for (mono_item, item_data) in mono_items {
|
||||
match mono_item {
|
||||
MonoItem::Fn(instance) => {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
let flags = tcx.codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
|
||||
instance,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ fn codegen_and_compile_fn<'tcx>(
|
|||
module: &mut dyn Module,
|
||||
instance: Instance<'tcx>,
|
||||
) {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
if tcx.codegen_instance_attrs(instance.def).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
tcx.dcx()
|
||||
.span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ fn predefine_mono_items<'tcx>(
|
|||
is_compiler_builtins,
|
||||
);
|
||||
let is_naked = tcx
|
||||
.codegen_fn_attrs(instance.def_id())
|
||||
.codegen_instance_attrs(instance.def)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED);
|
||||
module
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ permissions:
|
|||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
# TODO: remove when confish.sh is removed.
|
||||
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -59,14 +57,12 @@ jobs:
|
|||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-15.deb
|
||||
sudo dpkg --force-overwrite -i gcc-m68k-15.deb
|
||||
echo 'gcc-path = "/usr/lib/"' > config.toml
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
|
|
@ -86,16 +82,20 @@ jobs:
|
|||
- name: Build sample project with target defined as JSON spec
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh clean all
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
|
||||
# FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
|
||||
# supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
|
||||
# And as such, a wrong order of the object files in the linker command now fails with an undefined reference
|
||||
# to some symbols like __rustc::rust_panic.
|
||||
#CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
|
|
@ -104,9 +104,23 @@ jobs:
|
|||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run tests
|
||||
#run: |
|
||||
#./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
|
||||
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run Hello World!
|
||||
#run: |
|
||||
#./y.sh build --target-triple m68k-unknown-linux-gnu
|
||||
|
||||
#vm_dir=$(pwd)/vm
|
||||
#cd tests/hello-world
|
||||
#CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
|
||||
#sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
|
||||
#sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
|
||||
#expected_output="40"
|
||||
#test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
|
||||
|
||||
# Summary job for the merge queue.
|
||||
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ jobs:
|
|||
- name: Run tests
|
||||
run: |
|
||||
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
|
||||
echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
|
||||
# FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode.
|
||||
printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml
|
||||
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
|
|
|
|||
|
|
@ -1,502 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloctests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.160"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "coretests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlmalloc"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fortanix-sgx-abi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwind",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc_macro"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"rustc-literal-escaper",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler_builtins"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi-alloc"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"r-efi",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-literal-escaper"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-alloc"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-core"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-std"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"r-efi",
|
||||
"r-efi-alloc",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"rustc-demangle",
|
||||
"std_detect",
|
||||
"unwind",
|
||||
"wasi",
|
||||
"windows-targets 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc_macro",
|
||||
"profiler_builtins",
|
||||
"std",
|
||||
"test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwinding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwinding"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
[package]
|
||||
authors = ["rustc_codegen_gcc devs"]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "./sysroot_src/library/core" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
proc_macro = { path = "./sysroot_src/library/proc_macro" }
|
||||
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
# file to avoid symbol clashes with the system libgcc if possible. Note
|
||||
# that this number doesn't actually produce this many object files, we
|
||||
# just don't create more than this number of object files.
|
||||
#
|
||||
# It's a bit of a bummer that we have to pass this here, unfortunately.
|
||||
# Ideally this would be specified through an env var to Cargo so Cargo
|
||||
# knows how many CGUs are for this specific crate, but for now
|
||||
# per-crate configuration isn't specifiable in the environment.
|
||||
[profile.dev.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release]
|
||||
debug = "limited"
|
||||
#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.
|
||||
|
|
@ -1 +0,0 @@
|
|||
#![no_std]
|
||||
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
|
||||
use crate::config::{Channel, ConfigInfo};
|
||||
use crate::utils::{
|
||||
copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -53,11 +53,11 @@ impl BuildArg {
|
|||
}
|
||||
}
|
||||
|
||||
fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
||||
fn cleanup_sysroot_previous_build(library_dir: &Path) {
|
||||
// Cleanup for previous run
|
||||
// Clean target dir except for build scripts and incremental cache
|
||||
let _ = walk_dir(
|
||||
start_dir.join("target"),
|
||||
library_dir.join("target"),
|
||||
&mut |dir: &Path| {
|
||||
for top in &["debug", "release"] {
|
||||
let _ = fs::remove_dir_all(dir.join(top).join("build"));
|
||||
|
|
@ -95,31 +95,13 @@ fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
|||
&mut |_| Ok(()),
|
||||
false,
|
||||
);
|
||||
|
||||
let _ = fs::remove_file(start_dir.join("Cargo.lock"));
|
||||
let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
|
||||
let _ = fs::remove_dir_all(start_dir.join("sysroot"));
|
||||
}
|
||||
|
||||
pub fn create_build_sysroot_content(start_dir: &Path) -> Result<(), String> {
|
||||
if !start_dir.is_dir() {
|
||||
create_dir(start_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/Cargo.toml", start_dir.join("Cargo.toml"))?;
|
||||
copy_file("build_system/build_sysroot/Cargo.lock", start_dir.join("Cargo.lock"))?;
|
||||
|
||||
let src_dir = start_dir.join("src");
|
||||
if !src_dir.is_dir() {
|
||||
create_dir(&src_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/lib.rs", start_dir.join("src/lib.rs"))
|
||||
}
|
||||
|
||||
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
|
||||
let start_dir = get_sysroot_dir();
|
||||
|
||||
cleanup_sysroot_previous_build(&start_dir);
|
||||
create_build_sysroot_content(&start_dir)?;
|
||||
let library_dir = start_dir.join("sysroot_src").join("library");
|
||||
cleanup_sysroot_previous_build(&library_dir);
|
||||
|
||||
// Builds libs
|
||||
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
|
||||
|
|
@ -157,9 +139,13 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
rustflags.push_str(&cg_rustflags);
|
||||
}
|
||||
|
||||
args.push(&"--features");
|
||||
args.push(&"backtrace");
|
||||
|
||||
let mut env = env.clone();
|
||||
env.insert("RUSTFLAGS".to_string(), rustflags);
|
||||
run_command_with_output_and_env(&args, Some(&start_dir), Some(&env))?;
|
||||
let sysroot_dir = library_dir.join("sysroot");
|
||||
run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
|
||||
|
||||
// Copy files to sysroot
|
||||
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
|
||||
|
|
@ -169,7 +155,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
||||
};
|
||||
walk_dir(
|
||||
start_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
&mut copier.clone(),
|
||||
&mut copier,
|
||||
false,
|
||||
|
|
@ -178,7 +164,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
// Copy the source files to the sysroot (Rust for Linux needs this).
|
||||
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
|
||||
create_dir(&sysroot_src_path)?;
|
||||
run_command(&[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None)?;
|
||||
run_command(&[&"cp", &"-r", &library_dir, &sysroot_src_path], None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,11 +352,6 @@ impl ConfigInfo {
|
|||
None => return Err("no host found".to_string()),
|
||||
};
|
||||
|
||||
if self.target_triple.is_empty()
|
||||
&& let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE")
|
||||
{
|
||||
self.target_triple = overwrite.clone();
|
||||
}
|
||||
if self.target_triple.is_empty() {
|
||||
self.target_triple = self.host_triple.clone();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,19 +303,6 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn copy_file<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<(), String> {
|
||||
fs::copy(&from, &to)
|
||||
.map_err(|error| {
|
||||
format!(
|
||||
"Failed to copy file `{}` into `{}`: {:?}",
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display(),
|
||||
error
|
||||
)
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
|
||||
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
|
||||
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
|
||||
|
|
|
|||
|
|
@ -62,14 +62,14 @@ generate it in [gimple.md](./doc/gimple.md).
|
|||
|
||||
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. You can specify which linker to use via `CG_RUSTFLAGS="-Clinker=<linker>"`, for instance: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc"`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target and the linker to use: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
|
||||
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
Then, you can use it the following way:
|
||||
|
||||
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
|
||||
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
* Build your project by specifying the target specification file: `../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
|
||||
If you get the following error:
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
#![rustfmt::skip]
|
||||
#![rustfmt_skip]
|
||||
|
||||
extern crate mini_core;
|
||||
|
||||
|
|
@ -198,10 +198,17 @@ fn main() {
|
|||
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
|
||||
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
|
||||
|
||||
assert!(!const { intrinsics::needs_drop::<u8>() });
|
||||
assert!(!const { intrinsics::needs_drop::<[u8]>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
|
||||
/*
|
||||
* TODO: re-enable in the next sync.
|
||||
let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
|
||||
assert!(!u8_needs_drop);
|
||||
let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
|
||||
assert!(!slice_needs_drop);
|
||||
let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
|
||||
assert!(noisy_drop);
|
||||
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
|
||||
assert!(noisy_unsized_drop);
|
||||
*/
|
||||
|
||||
Unique {
|
||||
pointer: 0 as *const &str,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-06-28"
|
||||
channel = "nightly-2025-07-04"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
#[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) {
|
||||
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -971,7 +971,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
|
||||
ptr.dereference(self.location).to_rvalue()
|
||||
// (FractalFir): We insert a local here, to ensure this volatile load can't move across
|
||||
// blocks.
|
||||
let local = self.current_func().new_local(self.location, ty, "volatile_tmp");
|
||||
self.block.add_assignment(self.location, local, ptr.dereference(self.location).to_rvalue());
|
||||
local.to_rvalue()
|
||||
}
|
||||
|
||||
fn atomic_load(
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
|| tcx.codegen_instance_attrs(instance.def).inline
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
|
|
|
|||
|
|
@ -273,6 +273,10 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
|
|||
}
|
||||
|
||||
impl ExtraBackendMethods for GccCodegenBackend {
|
||||
fn supports_parallel(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn codegen_allocator(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
|
|
@ -341,8 +345,7 @@ impl Deref for SyncContext {
|
|||
}
|
||||
|
||||
unsafe impl Send for SyncContext {}
|
||||
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm".
|
||||
// TODO: disable it here by returning false in CodegenBackend::supports_parallel().
|
||||
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
|
||||
unsafe impl Sync for SyncContext {}
|
||||
|
||||
impl WriteBackendMethods for GccCodegenBackend {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(base::linkage_to_gcc(linkage));
|
||||
let decl = self.declare_fn(symbol_name, fn_abi);
|
||||
//let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
//let attrs = self.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
attributes::from_fn_attrs(self, decl, instance);
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||
#[cfg(feature = "master")]
|
||||
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
|
||||
} else {
|
||||
} else if visibility != Visibility::Default {
|
||||
#[cfg(feature = "master")]
|
||||
decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,3 +80,5 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
|
|||
tests/ui/coroutine/panic-drops-resume.rs
|
||||
tests/ui/coroutine/panic-drops.rs
|
||||
tests/ui/coroutine/panic-safe.rs
|
||||
tests/ui/process/nofile-limit.rs
|
||||
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ add_asm:
|
|||
ret"
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern "C" {
|
||||
fn add_asm(a: i64, b: i64) -> i64;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(const_black_box)]
|
||||
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
||||
|
|
@ -15,14 +13,14 @@ fn main() {
|
|||
}};
|
||||
}
|
||||
|
||||
check!(i32, (black_box(0.0f32) as i32));
|
||||
check!(i32, black_box(0.0f32) as i32);
|
||||
|
||||
check!(u64, (black_box(f32::NAN) as u64));
|
||||
check!(u128, (black_box(f32::NAN) as u128));
|
||||
check!(u64, black_box(f32::NAN) as u64);
|
||||
check!(u128, black_box(f32::NAN) as u128);
|
||||
|
||||
check!(i64, (black_box(f64::NAN) as i64));
|
||||
check!(u64, (black_box(f64::NAN) as u64));
|
||||
check!(i64, black_box(f64::NAN) as i64);
|
||||
check!(u64, black_box(f64::NAN) as u64);
|
||||
|
||||
check!(i16, (black_box(f32::MIN) as i16));
|
||||
check!(i16, (black_box(f32::MAX) as i16));
|
||||
check!(i16, black_box(f32::MIN) as i16);
|
||||
check!(i16, black_box(f32::MAX) as i16);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(const_black_box)]
|
||||
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
struct Struct {
|
||||
pointer: *const (),
|
||||
func: unsafe fn(*const ()),
|
||||
}
|
||||
|
||||
fn func(ptr: *const ()) {
|
||||
fn func(_ptr: *const ()) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
|
||||
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
|
||||
pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
|
||||
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
|
||||
|
|
@ -61,7 +59,7 @@ fn main() {
|
|||
panic!("error: mmap failed");
|
||||
}
|
||||
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
let p_count = (&raw mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(0);
|
||||
|
||||
// Trigger segfaults
|
||||
|
|
@ -94,7 +92,7 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe extern "C" fn segv_handler(_: i32, _: *mut (), _: *mut ()) {
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
let p_count = (&raw mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(p_count.read_volatile() + 1);
|
||||
let count = p_count.read_volatile();
|
||||
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
|
|||
llfn: &'ll Value,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) {
|
||||
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
let mut to_add = SmallVec::<[_; 16]>::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
|| tcx.codegen_instance_attrs(instance.def).inline
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
|
||||
llvm::set_linkage(lldecl, base::linkage_to_llvm(linkage));
|
||||
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
base::set_link_section(lldecl, attrs);
|
||||
let attrs = self.tcx.codegen_instance_attrs(instance.def);
|
||||
base::set_link_section(lldecl, &attrs);
|
||||
if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR)
|
||||
&& self.tcx.sess.target.supports_comdat()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2542,12 +2542,7 @@ fn add_order_independent_options(
|
|||
// sections to ensure we have all the data for PGO.
|
||||
let keep_metadata =
|
||||
crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
|
||||
if crate_type != CrateType::Executable || !sess.opts.unstable_opts.export_executable_symbols
|
||||
{
|
||||
cmd.gc_sections(keep_metadata);
|
||||
} else {
|
||||
cmd.no_gc_sections();
|
||||
}
|
||||
cmd.gc_sections(keep_metadata);
|
||||
}
|
||||
|
||||
cmd.set_output_kind(link_output_kind, crate_type, out_filename);
|
||||
|
|
|
|||
|
|
@ -326,7 +326,6 @@ pub(crate) trait Linker {
|
|||
link_or_cc_args(self, &[path]);
|
||||
}
|
||||
fn gc_sections(&mut self, keep_metadata: bool);
|
||||
fn no_gc_sections(&mut self);
|
||||
fn full_relro(&mut self);
|
||||
fn partial_relro(&mut self);
|
||||
fn no_relro(&mut self);
|
||||
|
|
@ -688,12 +687,6 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
if self.is_gnu || self.sess.target.is_like_wasm {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
if !self.is_gnu && !self.sess.target.is_like_wasm {
|
||||
return;
|
||||
|
|
@ -1010,10 +1003,6 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("/OPT:NOREF,NOICF");
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
|
@ -1243,10 +1232,6 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
// noop
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// Emscripten performs own optimizations
|
||||
self.cc_arg(match self.sess.opts.optimize {
|
||||
|
|
@ -1418,10 +1403,6 @@ impl<'a> Linker for WasmLd<'a> {
|
|||
self.link_arg("--gc-sections");
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and
|
||||
// only differentiates -O0 and -O1. It does not apply to LTO.
|
||||
|
|
@ -1567,10 +1548,6 @@ impl<'a> Linker for L4Bender<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// GNU-style linkers support optimization with -O. GNU ld doesn't
|
||||
// need a numeric argument, but other linkers do.
|
||||
|
|
@ -1734,10 +1711,6 @@ impl<'a> Linker for AixLinker<'a> {
|
|||
self.link_arg("-bgc");
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("-bnogc");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {
|
||||
|
|
@ -1982,8 +1955,6 @@ impl<'a> Linker for PtxLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
@ -2057,8 +2028,6 @@ impl<'a> Linker for LlbcLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
@ -2139,8 +2108,6 @@ impl<'a> Linker for BpfLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
LocalRef::Operand(operand) => {
|
||||
// Don't spill operands onto the stack in naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
||||
let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -390,9 +390,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
let mut num_untupled = None;
|
||||
|
||||
let codegen_fn_attrs = bx.tcx().codegen_fn_attrs(fx.instance.def_id());
|
||||
let naked = codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED);
|
||||
if naked {
|
||||
let codegen_fn_attrs = bx.tcx().codegen_instance_attrs(fx.instance.def);
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ fn prefix_and_suffix<'tcx>(
|
|||
let is_arm = tcx.sess.target.arch == "arm";
|
||||
let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode);
|
||||
|
||||
let attrs = tcx.codegen_fn_attrs(instance.def_id());
|
||||
let attrs = tcx.codegen_instance_attrs(instance.def);
|
||||
let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string());
|
||||
|
||||
// If no alignment is specified, an alignment of 4 bytes is used.
|
||||
|
|
|
|||
|
|
@ -611,11 +611,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() {
|
||||
Some(bx.tcx().codegen_fn_attrs(instance.def_id()))
|
||||
Some(bx.tcx().codegen_instance_attrs(instance.def))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None, Some(instance))
|
||||
bx.call(
|
||||
fn_ty,
|
||||
fn_attrs.as_deref(),
|
||||
Some(fn_abi),
|
||||
fn_ptr,
|
||||
&[],
|
||||
None,
|
||||
Some(instance),
|
||||
)
|
||||
} else {
|
||||
bx.get_static(def_id)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,12 +41,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
base::codegen_global_asm(cx, item_id);
|
||||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
if cx
|
||||
.tcx()
|
||||
.codegen_fn_attrs(instance.def_id())
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
let flags = cx.tcx().codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
naked_asm::codegen_naked_asm::<Bx::CodegenCx>(cx, instance, item_data);
|
||||
} else {
|
||||
base::codegen_instance::<Bx>(cx, instance);
|
||||
|
|
@ -75,7 +71,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
cx.predefine_static(def_id, linkage, visibility, symbol_name);
|
||||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
let attrs = cx.tcx().codegen_fn_attrs(instance.def_id());
|
||||
let attrs = cx.tcx().codegen_instance_attrs(instance.def);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
// do not define this function; it will become a global assembly block
|
||||
|
|
|
|||
|
|
@ -936,7 +936,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
if let Some(fn_val) = self.get_fn_alloc(id) {
|
||||
let align = match fn_val {
|
||||
FnVal::Instance(instance) => {
|
||||
self.tcx.codegen_fn_attrs(instance.def_id()).alignment.unwrap_or(Align::ONE)
|
||||
self.tcx.codegen_instance_attrs(instance.def).alignment.unwrap_or(Align::ONE)
|
||||
}
|
||||
// Machine-specific extra functions currently do not support alignment restrictions.
|
||||
FnVal::Other(_) => Align::ONE,
|
||||
|
|
|
|||
|
|
@ -1237,9 +1237,55 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
|
|||
return None;
|
||||
}
|
||||
|
||||
warn_on_confusing_output_filename_flag(early_dcx, &matches, args);
|
||||
|
||||
Some(matches)
|
||||
}
|
||||
|
||||
/// Warn if `-o` is used without a space between the flag name and the value
|
||||
/// and the value is a high-value confusables,
|
||||
/// e.g. `-optimize` instead of `-o optimize`, see issue #142812.
|
||||
fn warn_on_confusing_output_filename_flag(
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
matches: &getopts::Matches,
|
||||
args: &[String],
|
||||
) {
|
||||
fn eq_ignore_separators(s1: &str, s2: &str) -> bool {
|
||||
let s1 = s1.replace('-', "_");
|
||||
let s2 = s2.replace('-', "_");
|
||||
s1 == s2
|
||||
}
|
||||
|
||||
if let Some(name) = matches.opt_str("o")
|
||||
&& let Some(suspect) = args.iter().find(|arg| arg.starts_with("-o") && *arg != "-o")
|
||||
{
|
||||
let filename = suspect.strip_prefix("-").unwrap_or(suspect);
|
||||
let optgroups = config::rustc_optgroups();
|
||||
let fake_args = ["optimize", "o0", "o1", "o2", "o3", "ofast", "og", "os", "oz"];
|
||||
|
||||
// Check if provided filename might be confusing in conjunction with `-o` flag,
|
||||
// i.e. consider `-o{filename}` such as `-optimize` with `filename` being `ptimize`.
|
||||
// There are high-value confusables, for example:
|
||||
// - Long name of flags, e.g. `--out-dir` vs `-out-dir`
|
||||
// - C compiler flag, e.g. `optimize`, `o0`, `o1`, `o2`, `o3`, `ofast`.
|
||||
// - Codegen flags, e.g. `pt-level` of `-opt-level`.
|
||||
if optgroups.iter().any(|option| eq_ignore_separators(option.long_name(), filename))
|
||||
|| config::CG_OPTIONS.iter().any(|option| eq_ignore_separators(option.name(), filename))
|
||||
|| fake_args.iter().any(|arg| eq_ignore_separators(arg, filename))
|
||||
{
|
||||
early_dcx.early_warn(
|
||||
"option `-o` has no space between flag name and value, which can be confusing",
|
||||
);
|
||||
early_dcx.early_note(format!(
|
||||
"output filename `-o {name}` is applied instead of a flag named `o{name}`"
|
||||
));
|
||||
early_dcx.early_help(format!(
|
||||
"insert a space between `-o` and `{name}` if this is intentional: `-o {name}`"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use rustc_ast::token::Delimiter;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::util::literal;
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
|
||||
attr, token, tokenstream,
|
||||
self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind,
|
||||
UnOp, attr, token, tokenstream,
|
||||
};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
|
|
@ -766,4 +766,10 @@ impl<'a> ExtCtxt<'a> {
|
|||
span,
|
||||
)
|
||||
}
|
||||
|
||||
// Builds an attribute fully manually.
|
||||
pub fn attr_nested(&self, inner: AttrItem, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_from_item(g, inner, None, ast::AttrStyle::Outer, span)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ pub enum Target {
|
|||
Union,
|
||||
Trait,
|
||||
TraitAlias,
|
||||
Impl,
|
||||
Impl { of_trait: bool },
|
||||
Expression,
|
||||
Statement,
|
||||
Arm,
|
||||
|
|
@ -51,7 +51,7 @@ pub enum Target {
|
|||
ForeignFn,
|
||||
ForeignStatic,
|
||||
ForeignTy,
|
||||
GenericParam(GenericParamKind),
|
||||
GenericParam { kind: GenericParamKind, has_default: bool },
|
||||
MacroDef,
|
||||
Param,
|
||||
PatField,
|
||||
|
|
@ -86,14 +86,14 @@ impl Target {
|
|||
| Target::Union
|
||||
| Target::Trait
|
||||
| Target::TraitAlias
|
||||
| Target::Impl
|
||||
| Target::Impl { .. }
|
||||
| Target::Expression
|
||||
| Target::Statement
|
||||
| Target::Arm
|
||||
| Target::ForeignFn
|
||||
| Target::ForeignStatic
|
||||
| Target::ForeignTy
|
||||
| Target::GenericParam(_)
|
||||
| Target::GenericParam { .. }
|
||||
| Target::MacroDef
|
||||
| Target::Param
|
||||
| Target::PatField
|
||||
|
|
@ -119,7 +119,7 @@ impl Target {
|
|||
ItemKind::Union(..) => Target::Union,
|
||||
ItemKind::Trait(..) => Target::Trait,
|
||||
ItemKind::TraitAlias(..) => Target::TraitAlias,
|
||||
ItemKind::Impl { .. } => Target::Impl,
|
||||
ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ impl Target {
|
|||
DefKind::Union => Target::Union,
|
||||
DefKind::Trait => Target::Trait,
|
||||
DefKind::TraitAlias => Target::TraitAlias,
|
||||
DefKind::Impl { .. } => Target::Impl,
|
||||
DefKind::Impl { of_trait } => Target::Impl { of_trait },
|
||||
_ => panic!("impossible case reached"),
|
||||
}
|
||||
}
|
||||
|
|
@ -169,11 +169,17 @@ impl Target {
|
|||
|
||||
pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
|
||||
match generic_param.kind {
|
||||
hir::GenericParamKind::Type { .. } => Target::GenericParam(GenericParamKind::Type),
|
||||
hir::GenericParamKind::Type { default, .. } => Target::GenericParam {
|
||||
kind: GenericParamKind::Type,
|
||||
has_default: default.is_some(),
|
||||
},
|
||||
hir::GenericParamKind::Lifetime { .. } => {
|
||||
Target::GenericParam(GenericParamKind::Lifetime)
|
||||
Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }
|
||||
}
|
||||
hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
|
||||
hir::GenericParamKind::Const { default, .. } => Target::GenericParam {
|
||||
kind: GenericParamKind::Const,
|
||||
has_default: default.is_some(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +202,8 @@ impl Target {
|
|||
Target::Union => "union",
|
||||
Target::Trait => "trait",
|
||||
Target::TraitAlias => "trait alias",
|
||||
Target::Impl => "implementation block",
|
||||
Target::Impl { of_trait: false } => "inherent implementation block",
|
||||
Target::Impl { of_trait: true } => "trait implementation block",
|
||||
Target::Expression => "expression",
|
||||
Target::Statement => "statement",
|
||||
Target::Arm => "match arm",
|
||||
|
|
@ -210,7 +217,7 @@ impl Target {
|
|||
Target::ForeignFn => "foreign function",
|
||||
Target::ForeignStatic => "foreign static item",
|
||||
Target::ForeignTy => "foreign type",
|
||||
Target::GenericParam(kind) => match kind {
|
||||
Target::GenericParam { kind, has_default: _ } => match kind {
|
||||
GenericParamKind::Type => "type parameter",
|
||||
GenericParamKind::Lifetime => "lifetime parameter",
|
||||
GenericParamKind::Const => "const parameter",
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be imp
|
|||
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
|
||||
|
||||
hir_analysis_drop_impl_on_wrong_item =
|
||||
the `Drop` trait may only be implemented for local structs, enums, and unions
|
||||
the `{$trait_}` trait may only be implemented for local structs, enums, and unions
|
||||
.label = must be a struct, enum, or union in the current crate
|
||||
|
||||
hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ pub(super) fn check_trait<'tcx>(
|
|||
let lang_items = tcx.lang_items();
|
||||
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
|
||||
checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
|
||||
checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
|
||||
checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
|
||||
checker.check(lang_items.const_param_ty_trait(), |checker| {
|
||||
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
|
||||
|
|
@ -83,7 +84,10 @@ fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaran
|
|||
|
||||
let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
|
||||
|
||||
Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }))
|
||||
Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem {
|
||||
span: impl_.self_ty.span,
|
||||
trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
|
||||
}))
|
||||
}
|
||||
|
||||
fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ pub(crate) struct DropImplOnWrongItem {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub trait_: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ use smallvec::smallvec;
|
|||
|
||||
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
|
||||
/// must be added to the struct header.
|
||||
pub(crate) type RequiredPredicates<'tcx> =
|
||||
FxIndexMap<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>, Span>;
|
||||
pub(crate) type RequiredPredicates<'tcx> = FxIndexMap<ty::ArgOutlivesPredicate<'tcx>, Span>;
|
||||
|
||||
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
|
||||
/// outlives_component and add it to `required_predicates`
|
||||
|
|
|
|||
|
|
@ -161,16 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Resume type defaults to `()` if the coroutine has no argument.
|
||||
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
|
||||
|
||||
// In the new solver, we can just instantiate this eagerly
|
||||
// with the witness. This will ensure that goals that don't need
|
||||
// to stall on interior types will get processed eagerly.
|
||||
let interior = if self.next_trait_solver() {
|
||||
Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args)
|
||||
} else {
|
||||
self.next_ty_var(expr_span)
|
||||
};
|
||||
|
||||
self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior));
|
||||
let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args);
|
||||
|
||||
// Coroutines that come from coroutine closures have not yet determined
|
||||
// their kind ty, so make a fresh infer var which will be constrained
|
||||
|
|
|
|||
|
|
@ -625,50 +625,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// trigger query cycle ICEs, as doing so requires MIR.
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
|
||||
let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut());
|
||||
debug!(?coroutines);
|
||||
let ty::TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
|
||||
else {
|
||||
bug!();
|
||||
};
|
||||
|
||||
let mut obligations = vec![];
|
||||
|
||||
if !self.next_trait_solver() {
|
||||
for &(coroutine_def_id, interior) in coroutines.iter() {
|
||||
debug!(?coroutine_def_id);
|
||||
|
||||
// Create the `CoroutineWitness` type that we will unify with `interior`.
|
||||
let args = ty::GenericArgs::identity_for_item(
|
||||
self.tcx,
|
||||
self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
|
||||
);
|
||||
let witness =
|
||||
Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
|
||||
|
||||
// Unify `interior` with `witness` and collect all the resulting obligations.
|
||||
let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
|
||||
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
|
||||
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
|
||||
};
|
||||
let ok = self
|
||||
.at(&self.misc(span), self.param_env)
|
||||
// Will never define opaque types, as all we do is instantiate a type variable.
|
||||
.eq(DefineOpaqueTypes::Yes, interior, witness)
|
||||
.expect("Failed to unify coroutine interior type");
|
||||
|
||||
obligations.extend(ok.obligations);
|
||||
}
|
||||
}
|
||||
|
||||
if !coroutines.is_empty() {
|
||||
obligations.extend(
|
||||
if defining_opaque_types_and_generators
|
||||
.iter()
|
||||
.any(|def_id| self.tcx.is_coroutine(def_id.to_def_id()))
|
||||
{
|
||||
self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(
|
||||
self.fulfillment_cx
|
||||
.borrow_mut()
|
||||
.drain_stalled_obligations_for_coroutines(&self.infcx),
|
||||
.drain_stalled_obligations_for_coroutines(&self.infcx)
|
||||
.into_iter()
|
||||
.map(|o| (o.predicate, o.cause)),
|
||||
);
|
||||
}
|
||||
|
||||
self.typeck_results
|
||||
.borrow_mut()
|
||||
.coroutine_stalled_predicates
|
||||
.extend(obligations.into_iter().map(|o| (o.predicate, o.cause)));
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
|
|
|||
|
|
@ -1650,7 +1650,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
|
||||
let sources =
|
||||
applicable_candidates.iter().map(|p| self.candidate_source(p.0, self_ty)).collect();
|
||||
return Some(Err(MethodError::Ambiguity(sources)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
|
|||
|
||||
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>,
|
||||
|
||||
pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, Ty<'tcx>)>>,
|
||||
|
||||
pub(super) deferred_repeat_expr_checks:
|
||||
RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>,
|
||||
|
||||
|
|
@ -103,7 +101,6 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
|||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
deferred_transmute_checks: RefCell::new(Vec::new()),
|
||||
deferred_asm_checks: RefCell::new(Vec::new()),
|
||||
deferred_coroutine_interiors: RefCell::new(Vec::new()),
|
||||
deferred_repeat_expr_checks: RefCell::new(Vec::new()),
|
||||
diverging_type_vars: RefCell::new(Default::default()),
|
||||
infer_var_info: RefCell::new(Default::default()),
|
||||
|
|
|
|||
|
|
@ -116,9 +116,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
let region_obligations = self.take_registered_region_obligations();
|
||||
let region_assumptions = self.take_registered_region_assumptions();
|
||||
debug!(?region_obligations);
|
||||
let region_constraints = self.with_region_constraints(|region_constraints| {
|
||||
make_query_region_constraints(tcx, region_obligations, region_constraints)
|
||||
make_query_region_constraints(
|
||||
tcx,
|
||||
region_obligations,
|
||||
region_constraints,
|
||||
region_assumptions,
|
||||
)
|
||||
});
|
||||
debug!(?region_constraints);
|
||||
|
||||
|
|
@ -169,6 +175,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
self.register_outlives_constraint(predicate, cause);
|
||||
}
|
||||
|
||||
for assumption in &query_response.value.region_constraints.assumptions {
|
||||
let assumption = instantiate_value(self.tcx, &result_args, *assumption);
|
||||
self.register_region_assumption(assumption);
|
||||
}
|
||||
|
||||
let user_result: R =
|
||||
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
|
||||
|
||||
|
|
@ -292,6 +303,18 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}),
|
||||
);
|
||||
|
||||
// FIXME(higher_ranked_auto): Optimize this to instantiate all assumptions
|
||||
// at once, rather than calling `instantiate_value` repeatedly which may
|
||||
// create more universes.
|
||||
output_query_region_constraints.assumptions.extend(
|
||||
query_response
|
||||
.value
|
||||
.region_constraints
|
||||
.assumptions
|
||||
.iter()
|
||||
.map(|&r_c| instantiate_value(self.tcx, &result_args, r_c)),
|
||||
);
|
||||
|
||||
let user_result: R =
|
||||
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
|
||||
|
||||
|
|
@ -567,6 +590,7 @@ pub fn make_query_region_constraints<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
outlives_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
) -> QueryRegionConstraints<'tcx> {
|
||||
let RegionConstraintData { constraints, verifys } = region_constraints;
|
||||
|
||||
|
|
@ -602,5 +626,5 @@ pub fn make_query_region_constraints<'tcx>(
|
|||
}))
|
||||
.collect();
|
||||
|
||||
QueryRegionConstraints { outlives }
|
||||
QueryRegionConstraints { outlives, assumptions }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ pub struct InferCtxtInner<'tcx> {
|
|||
/// that all type inference variables have been bound and so forth.
|
||||
region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
|
||||
|
||||
/// The outlives bounds that we assume must hold about placeholders that
|
||||
/// come from instantiating the binder of coroutine-witnesses. These bounds
|
||||
/// are deduced from the well-formedness of the witness's types, and are
|
||||
/// necessary because of the way we anonymize the regions in a coroutine,
|
||||
/// which may cause types to no longer be considered well-formed.
|
||||
region_assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
|
||||
/// Caches for opaque type inference.
|
||||
opaque_type_storage: OpaqueTypeStorage<'tcx>,
|
||||
}
|
||||
|
|
@ -164,7 +171,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
int_unification_storage: Default::default(),
|
||||
float_unification_storage: Default::default(),
|
||||
region_constraint_storage: Some(Default::default()),
|
||||
region_obligations: vec![],
|
||||
region_obligations: Default::default(),
|
||||
region_assumptions: Default::default(),
|
||||
opaque_type_storage: Default::default(),
|
||||
}
|
||||
}
|
||||
|
|
@ -174,6 +182,11 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
&self.region_obligations
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn region_assumptions(&self) -> &[ty::ArgOutlivesPredicate<'tcx>] {
|
||||
&self.region_assumptions
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> {
|
||||
self.projection_cache.with_log(&mut self.undo_log)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
|
||||
use rustc_middle::{bug, ty};
|
||||
use tracing::debug;
|
||||
|
|
@ -39,6 +39,9 @@ pub struct OutlivesEnvironment<'tcx> {
|
|||
/// optimized in the future, though.
|
||||
region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
/// Assumptions that come from the well-formedness of coroutines that we prove
|
||||
/// auto trait bounds for during the type checking of this body.
|
||||
higher_ranked_assumptions: FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
}
|
||||
|
||||
/// "Region-bound pairs" tracks outlives relations that are known to
|
||||
|
|
@ -52,6 +55,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
|
||||
higher_ranked_assumptions: FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
) -> Self {
|
||||
let mut region_relation = TransitiveRelationBuilder::default();
|
||||
let mut region_bound_pairs = RegionBoundPairs::default();
|
||||
|
|
@ -88,6 +92,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
|
|||
known_type_outlives,
|
||||
free_region_map: FreeRegionMap { relation: region_relation.freeze() },
|
||||
region_bound_pairs,
|
||||
higher_ranked_assumptions,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,4 +107,8 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
|
|||
pub fn known_type_outlives(&self) -> &[ty::PolyTypeOutlivesPredicate<'tcx>] {
|
||||
&self.known_type_outlives
|
||||
}
|
||||
|
||||
pub fn higher_ranked_assumptions(&self) -> &FxHashSet<ty::ArgOutlivesPredicate<'tcx>> {
|
||||
&self.higher_ranked_assumptions
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use super::region_constraints::{RegionConstraintData, UndoLog};
|
|||
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
|
||||
use crate::infer::free_regions::RegionRelations;
|
||||
use crate::infer::lexical_region_resolve;
|
||||
use crate::infer::region_constraints::Constraint;
|
||||
|
||||
pub mod env;
|
||||
pub mod for_liveness;
|
||||
|
|
@ -54,18 +55,29 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
let storage = {
|
||||
let mut storage = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
assert!(
|
||||
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
inner.region_obligations
|
||||
inner.region_obligations,
|
||||
);
|
||||
assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
|
||||
inner.region_constraint_storage.take().expect("regions already resolved")
|
||||
};
|
||||
|
||||
// Filter out any region-region outlives assumptions that are implied by
|
||||
// coroutine well-formedness.
|
||||
if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
|
||||
storage.data.constraints.retain(|(constraint, _)| match *constraint {
|
||||
Constraint::RegSubReg(r1, r2) => !outlives_env
|
||||
.higher_ranked_assumptions()
|
||||
.contains(&ty::OutlivesPredicate(r2.into(), r1)),
|
||||
_ => true,
|
||||
});
|
||||
}
|
||||
|
||||
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
|
||||
|
||||
let (lexical_region_resolutions, errors) =
|
||||
|
|
@ -93,6 +105,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
"region_obligations not empty: {:#?}",
|
||||
self.inner.borrow().region_obligations
|
||||
);
|
||||
assert!(
|
||||
self.inner.borrow().region_assumptions.is_empty(),
|
||||
"region_assumptions not empty: {:#?}",
|
||||
self.inner.borrow().region_assumptions
|
||||
);
|
||||
|
||||
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
|
|||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn register_outlives_constraint(
|
||||
&self,
|
||||
ty::OutlivesPredicate(arg, r2): ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
ty::OutlivesPredicate(arg, r2): ty::ArgOutlivesPredicate<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) {
|
||||
match arg.kind() {
|
||||
|
|
@ -170,6 +170,16 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
|
||||
}
|
||||
|
||||
pub fn register_region_assumption(&self, assumption: ty::ArgOutlivesPredicate<'tcx>) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.undo_log.push(UndoLog::PushRegionAssumption);
|
||||
inner.region_assumptions.push(assumption);
|
||||
}
|
||||
|
||||
pub fn take_registered_region_assumptions(&self) -> Vec<ty::ArgOutlivesPredicate<'tcx>> {
|
||||
std::mem::take(&mut self.inner.borrow_mut().region_assumptions)
|
||||
}
|
||||
|
||||
/// Process the region obligations that must be proven (during
|
||||
/// `regionck`) for the given `body_id`, given information about
|
||||
/// the region bounds in scope and so forth.
|
||||
|
|
@ -220,6 +230,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let (sup_type, sub_region) =
|
||||
(sup_type, sub_region).fold_with(&mut OpportunisticRegionResolver::new(self));
|
||||
|
||||
if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
|
||||
&& outlives_env
|
||||
.higher_ranked_assumptions()
|
||||
.contains(&ty::OutlivesPredicate(sup_type.into(), sub_region))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ pub(crate) enum UndoLog<'tcx> {
|
|||
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
|
||||
ProjectionCache(traits::UndoLog<'tcx>),
|
||||
PushTypeOutlivesConstraint,
|
||||
PushRegionAssumption,
|
||||
}
|
||||
|
||||
macro_rules! impl_from {
|
||||
|
|
@ -77,6 +78,9 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
|
|||
let popped = self.region_obligations.pop();
|
||||
assert_matches!(popped, Some(_), "pushed region constraint but could not pop it");
|
||||
}
|
||||
UndoLog::PushRegionAssumption => {
|
||||
self.region_assumptions.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1054,18 +1054,12 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
tcx.ensure_ok().check_mod_unstable_api_usage(module);
|
||||
});
|
||||
},
|
||||
{
|
||||
sess.time("unused_lib_feature_checking", || {
|
||||
rustc_passes::stability::check_unused_or_stable_features(tcx)
|
||||
});
|
||||
},
|
||||
{
|
||||
// We force these queries to run,
|
||||
// since they might not otherwise get called.
|
||||
// This marks the corresponding crate-level attributes
|
||||
// as used, and ensures that their values are valid.
|
||||
tcx.ensure_ok().limits(());
|
||||
tcx.ensure_ok().stability_index(());
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1585,6 +1585,8 @@ impl EarlyLintPass for DoubleNegations {
|
|||
if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind
|
||||
&& let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind
|
||||
&& !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _))
|
||||
// Don't lint if this jumps macro expansion boundary (Issue #143980)
|
||||
&& expr.span.eq_ctxt(inner.span)
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
DOUBLE_NEGATIONS,
|
||||
|
|
|
|||
|
|
@ -81,13 +81,18 @@ pub struct QueryResponse<'tcx, R> {
|
|||
#[derive(HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct QueryRegionConstraints<'tcx> {
|
||||
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
|
||||
pub assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
}
|
||||
|
||||
impl QueryRegionConstraints<'_> {
|
||||
/// Represents an empty (trivially true) set of region
|
||||
/// constraints.
|
||||
/// Represents an empty (trivially true) set of region constraints.
|
||||
///
|
||||
/// FIXME(higher_ranked_auto): This could still just be true if there are only assumptions?
|
||||
/// Because I don't expect for us to get cases where an assumption from one query would
|
||||
/// discharge a requirement from another query, which is a potential problem if we did throw
|
||||
/// away these assumptions because there were no constraints.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.outlives.is_empty()
|
||||
self.outlives.is_empty() && self.assumptions.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +135,7 @@ impl<'tcx, R> QueryResponse<'tcx, R> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type QueryOutlivesConstraint<'tcx> =
|
||||
(ty::OutlivesPredicate<'tcx, GenericArg<'tcx>>, ConstraintCategory<'tcx>);
|
||||
pub type QueryOutlivesConstraint<'tcx> = (ty::ArgOutlivesPredicate<'tcx>, ConstraintCategory<'tcx>);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CanonicalParamEnvCache<'tcx> {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
|
||||
use rustc_attr_data_structures::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
|
|
@ -6,6 +8,26 @@ use rustc_span::Symbol;
|
|||
use rustc_target::spec::SanitizerSet;
|
||||
|
||||
use crate::mir::mono::Linkage;
|
||||
use crate::ty::{InstanceKind, TyCtxt};
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn codegen_instance_attrs(
|
||||
self,
|
||||
instance_kind: InstanceKind<'_>,
|
||||
) -> Cow<'tcx, CodegenFnAttrs> {
|
||||
let mut attrs = Cow::Borrowed(self.codegen_fn_attrs(instance_kind.def_id()));
|
||||
|
||||
// Drop the `#[naked]` attribute on non-item `InstanceKind`s, like the shims that
|
||||
// are generated for indirect function calls.
|
||||
if !matches!(instance_kind, InstanceKind::Item(_)) {
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
attrs.to_mut().flags.remove(CodegenFnAttrFlags::NAKED);
|
||||
}
|
||||
}
|
||||
|
||||
attrs
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||
pub struct CodegenFnAttrs {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ use rustc_ast::NodeId;
|
|||
use rustc_attr_data_structures::{
|
||||
self as attrs, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
|
||||
};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||
use rustc_feature::GateIssue;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
|
||||
use rustc_session::Session;
|
||||
|
|
@ -65,48 +64,6 @@ impl DeprecationEntry {
|
|||
}
|
||||
}
|
||||
|
||||
/// A stability index, giving the stability level for items and methods.
|
||||
#[derive(HashStable, Debug)]
|
||||
pub struct Index {
|
||||
/// This is mostly a cache, except the stabilities of local items
|
||||
/// are filled by the annotator.
|
||||
pub stab_map: LocalDefIdMap<Stability>,
|
||||
pub const_stab_map: LocalDefIdMap<ConstStability>,
|
||||
pub default_body_stab_map: LocalDefIdMap<DefaultBodyStability>,
|
||||
pub depr_map: LocalDefIdMap<DeprecationEntry>,
|
||||
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
|
||||
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
|
||||
/// exists, then this map will have a `impliee -> implier` entry.
|
||||
///
|
||||
/// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
|
||||
/// specify their implications (both `implies` and `implied_by`). If only one of the two
|
||||
/// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
|
||||
/// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
|
||||
/// reported, only the `#[stable]` attribute information is available, so the map is necessary
|
||||
/// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
|
||||
/// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
|
||||
/// unstable feature" error for a feature that was implied.
|
||||
pub implications: UnordMap<Symbol, Symbol>,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
pub fn local_stability(&self, def_id: LocalDefId) -> Option<Stability> {
|
||||
self.stab_map.get(&def_id).copied()
|
||||
}
|
||||
|
||||
pub fn local_const_stability(&self, def_id: LocalDefId) -> Option<ConstStability> {
|
||||
self.const_stab_map.get(&def_id).copied()
|
||||
}
|
||||
|
||||
pub fn local_default_body_stability(&self, def_id: LocalDefId) -> Option<DefaultBodyStability> {
|
||||
self.default_body_stab_map.get(&def_id).copied()
|
||||
}
|
||||
|
||||
pub fn local_deprecation_entry(&self, def_id: LocalDefId) -> Option<DeprecationEntry> {
|
||||
self.depr_map.get(&def_id).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_unstable(
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
// If the function is #[naked] or contains any other attribute that requires exactly-once
|
||||
// instantiation:
|
||||
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
|
||||
if codegen_fn_attrs.contains_extern_indicator()
|
||||
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
|
|
@ -219,7 +219,7 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
// functions the same as those that unconditionally get LocalCopy codegen. It's only when
|
||||
// we get here that we can at least not codegen a #[inline(never)] generic function in all
|
||||
// of our CGUs.
|
||||
if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline
|
||||
if let InlineAttr::Never = codegen_fn_attrs.inline
|
||||
&& self.is_generic_fn()
|
||||
{
|
||||
return InstantiationMode::GloballyShared { may_conflict: true };
|
||||
|
|
@ -234,14 +234,13 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
}
|
||||
|
||||
pub fn explicit_linkage(&self, tcx: TyCtxt<'tcx>) -> Option<Linkage> {
|
||||
let def_id = match *self {
|
||||
MonoItem::Fn(ref instance) => instance.def_id(),
|
||||
MonoItem::Static(def_id) => def_id,
|
||||
let instance_kind = match *self {
|
||||
MonoItem::Fn(ref instance) => instance.def,
|
||||
MonoItem::Static(def_id) => InstanceKind::Item(def_id),
|
||||
MonoItem::GlobalAsm(..) => return None,
|
||||
};
|
||||
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
codegen_fn_attrs.linkage
|
||||
tcx.codegen_instance_attrs(instance_kind).linkage
|
||||
}
|
||||
|
||||
/// Returns `true` if this instance is instantiable - whether it has no unsatisfied
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
|||
use crate::middle::lib_features::LibFeatures;
|
||||
use crate::middle::privacy::EffectiveVisibilities;
|
||||
use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
|
||||
use crate::middle::stability::{self, DeprecationEntry};
|
||||
use crate::middle::stability::DeprecationEntry;
|
||||
use crate::mir::interpret::{
|
||||
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
|
||||
EvalToValTreeResult, GlobalId, LitToConstInput,
|
||||
|
|
@ -988,7 +988,7 @@ rustc_queries! {
|
|||
}
|
||||
|
||||
query coroutine_hidden_types(
|
||||
def_id: DefId
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
|
||||
desc { "looking up the hidden types stored across await points in a coroutine" }
|
||||
}
|
||||
|
|
@ -1505,6 +1505,15 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// Returns the `CodegenFnAttrs` for the item at `def_id`.
|
||||
///
|
||||
/// If possible, use `tcx.codegen_instance_attrs` instead. That function takes the
|
||||
/// instance kind into account.
|
||||
///
|
||||
/// For example, the `#[naked]` attribute should be applied for `InstanceKind::Item`,
|
||||
/// but should not be applied if the instance kind is `InstanceKind::ReifyShim`.
|
||||
/// Using this query would include the attribute regardless of the actual instance
|
||||
/// kind at the call site.
|
||||
query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs {
|
||||
desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) }
|
||||
arena_cache
|
||||
|
|
@ -2162,6 +2171,18 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
arena_cache
|
||||
}
|
||||
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
|
||||
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
|
||||
/// exists, then this map will have a `impliee -> implier` entry.
|
||||
///
|
||||
/// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
|
||||
/// specify their implications (both `implies` and `implied_by`). If only one of the two
|
||||
/// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
|
||||
/// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
|
||||
/// reported, only the `#[stable]` attribute information is available, so the map is necessary
|
||||
/// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
|
||||
/// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
|
||||
/// unstable feature" error for a feature that was implied.
|
||||
query stability_implications(_: CrateNum) -> &'tcx UnordMap<Symbol, Symbol> {
|
||||
arena_cache
|
||||
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
|
||||
|
|
@ -2268,11 +2289,6 @@ rustc_queries! {
|
|||
desc { "fetching potentially unused trait imports" }
|
||||
}
|
||||
|
||||
query stability_index(_: ()) -> &'tcx stability::Index {
|
||||
arena_cache
|
||||
eval_always
|
||||
desc { "calculating the stability index for the local crate" }
|
||||
}
|
||||
/// All available crates in the graph, including those that should not be user-facing
|
||||
/// (such as private crates).
|
||||
query crates(_: ()) -> &'tcx [CrateNum] {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, Canonica
|
|||
use crate::lint::lint_level;
|
||||
use crate::metadata::ModChild;
|
||||
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
|
||||
use crate::middle::{resolve_bound_vars, stability};
|
||||
use crate::middle::resolve_bound_vars;
|
||||
use crate::mir::interpret::{self, Allocation, ConstAllocation};
|
||||
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
|
||||
use crate::query::plumbing::QuerySystem;
|
||||
|
|
@ -163,6 +163,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type BoundRegion = ty::BoundRegion;
|
||||
type PlaceholderRegion = ty::PlaceholderRegion;
|
||||
|
||||
type RegionAssumptions = &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>>;
|
||||
|
||||
type ParamEnv = ty::ParamEnv<'tcx>;
|
||||
type Predicate = Predicate<'tcx>;
|
||||
|
||||
|
|
@ -714,17 +716,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self,
|
||||
defining_anchor: Self::LocalDefId,
|
||||
) -> Self::LocalDefIds {
|
||||
if self.next_trait_solver_globally() {
|
||||
let coroutines_defined_by = self
|
||||
.nested_bodies_within(defining_anchor)
|
||||
.iter()
|
||||
.filter(|def_id| self.is_coroutine(def_id.to_def_id()));
|
||||
self.mk_local_def_ids_from_iter(
|
||||
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
|
||||
)
|
||||
} else {
|
||||
self.opaque_types_defined_by(defining_anchor)
|
||||
}
|
||||
let coroutines_defined_by = self
|
||||
.nested_bodies_within(defining_anchor)
|
||||
.iter()
|
||||
.filter(|def_id| self.is_coroutine(def_id.to_def_id()));
|
||||
self.mk_local_def_ids_from_iter(
|
||||
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -882,6 +880,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
|
||||
valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>,
|
||||
patterns: InternedSet<'tcx, List<ty::Pattern<'tcx>>>,
|
||||
outlives: InternedSet<'tcx, List<ty::ArgOutlivesPredicate<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtInterners<'tcx> {
|
||||
|
|
@ -919,6 +918,7 @@ impl<'tcx> CtxtInterners<'tcx> {
|
|||
offset_of: InternedSet::with_capacity(N),
|
||||
valtree: InternedSet::with_capacity(N),
|
||||
patterns: InternedSet::with_capacity(N),
|
||||
outlives: InternedSet::with_capacity(N),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1807,10 +1807,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn stability(self) -> &'tcx stability::Index {
|
||||
self.stability_index(())
|
||||
}
|
||||
|
||||
pub fn features(self) -> &'tcx rustc_feature::Features {
|
||||
self.features_query(())
|
||||
}
|
||||
|
|
@ -2700,6 +2696,7 @@ slice_interners!(
|
|||
captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
|
||||
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
|
||||
patterns: pub mk_patterns(Pattern<'tcx>),
|
||||
outlives: pub mk_outlives(ty::ArgOutlivesPredicate<'tcx>),
|
||||
);
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
|
|
@ -3115,6 +3112,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
|
||||
}
|
||||
|
||||
pub fn mk_outlives_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: CollectAndApply<
|
||||
ty::ArgOutlivesPredicate<'tcx>,
|
||||
&'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
>,
|
||||
{
|
||||
T::collect_and_apply(iter, |xs| self.mk_outlives(xs))
|
||||
}
|
||||
|
||||
/// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
|
||||
/// typically generated by `#[derive(LintDiagnostic)]`).
|
||||
#[track_caller]
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ pub use self::opaque_types::OpaqueTypeKey;
|
|||
pub use self::parameterized::ParameterizedOverTcx;
|
||||
pub use self::pattern::{Pattern, PatternKind};
|
||||
pub use self::predicate::{
|
||||
AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
|
||||
AliasTerm, ArgOutlivesPredicate, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
|
||||
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef,
|
||||
HostEffectPredicate, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
|
||||
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
|
|||
pub type OutlivesPredicate<'tcx, T> = ir::OutlivesPredicate<TyCtxt<'tcx>, T>;
|
||||
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::Region<'tcx>>;
|
||||
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, Ty<'tcx>>;
|
||||
pub type ArgOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>;
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
|
||||
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
|
||||
|
|
|
|||
|
|
@ -802,4 +802,5 @@ list_fold! {
|
|||
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
|
||||
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
|
||||
&'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
|
||||
&'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> : mk_outlives,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, CoverageStatus, find_attr};
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind};
|
||||
|
|
@ -5,7 +6,6 @@ use rustc_middle::mir::{Body, Statement, StatementKind};
|
|||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::sym;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::coverage::counters::node_flow::make_node_counters;
|
||||
|
|
@ -58,26 +58,20 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
/// Query implementation for `coverage_attr_on`.
|
||||
fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
// Check for annotations directly on this def.
|
||||
if let Some(attr) = tcx.get_attr(def_id, sym::coverage) {
|
||||
match attr.meta_item_list().as_deref() {
|
||||
Some([item]) if item.has_name(sym::off) => return false,
|
||||
Some([item]) if item.has_name(sym::on) => return true,
|
||||
Some(_) | None => {
|
||||
// Other possibilities should have been rejected by `rustc_parse::validate_attr`.
|
||||
// Use `span_delayed_bug` to avoid an ICE in failing builds (#127880).
|
||||
tcx.dcx().span_delayed_bug(attr.span(), "unexpected value of coverage attribute");
|
||||
}
|
||||
if let Some(coverage_status) =
|
||||
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Coverage(_, status) => status)
|
||||
{
|
||||
*coverage_status == CoverageStatus::On
|
||||
} else {
|
||||
match tcx.opt_local_parent(def_id) {
|
||||
// Check the parent def (and so on recursively) until we find an
|
||||
// enclosing attribute or reach the crate root.
|
||||
Some(parent) => tcx.coverage_attr_on(parent),
|
||||
// We reached the crate root without seeing a coverage attribute, so
|
||||
// allow coverage instrumentation by default.
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
match tcx.opt_local_parent(def_id) {
|
||||
// Check the parent def (and so on recursively) until we find an
|
||||
// enclosing attribute or reach the crate root.
|
||||
Some(parent) => tcx.coverage_attr_on(parent),
|
||||
// We reached the crate root without seeing a coverage attribute, so
|
||||
// allow coverage instrumentation by default.
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Query implementation for `coverage_ids_info`.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -318,6 +318,7 @@ pub fn check_builtin_meta_item(
|
|||
| sym::rustc_layout_scalar_valid_range_end
|
||||
| sym::no_implicit_prelude
|
||||
| sym::automatically_derived
|
||||
| sym::coverage
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -560,7 +560,8 @@ passes_only_has_effect_on =
|
|||
`#[{$attr_name}]` only has an effect on {$target_name ->
|
||||
[function] functions
|
||||
[module] modules
|
||||
[implementation_block] implementation blocks
|
||||
[trait_implementation_block] trait implementation blocks
|
||||
[inherent_implementation_block] inherent implementation blocks
|
||||
*[unspecified] (unspecified--this is a compiler bug)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,17 @@ use std::slice;
|
|||
|
||||
use rustc_abi::{Align, ExternAbi, Size};
|
||||
use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms};
|
||||
use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr};
|
||||
use rustc_attr_data_structures::{
|
||||
AttributeKind, InlineAttr, PartialConstStability, ReprAttr, Stability, StabilityLevel,
|
||||
find_attr,
|
||||
};
|
||||
use rustc_attr_parsing::{AttributeParser, Late};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
||||
use rustc_feature::{
|
||||
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
|
||||
BuiltinAttribute,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
|
|
@ -36,6 +42,7 @@ use rustc_session::lint;
|
|||
use rustc_session::lint::builtin::{
|
||||
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
|
||||
USELESS_DEPRECATED,
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::edition::Edition;
|
||||
|
|
@ -161,12 +168,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
sym::automatically_derived,
|
||||
*attr_span,
|
||||
target,
|
||||
Target::Impl,
|
||||
Target::Impl { of_trait: true },
|
||||
),
|
||||
Attribute::Parsed(
|
||||
AttributeKind::Stability { span, .. }
|
||||
| AttributeKind::ConstStability { span, .. },
|
||||
) => self.check_stability_promotable(*span, target),
|
||||
AttributeKind::Stability {
|
||||
span: attr_span,
|
||||
stability: Stability { level, feature },
|
||||
}
|
||||
| AttributeKind::ConstStability {
|
||||
span: attr_span,
|
||||
stability: PartialConstStability { level, feature, .. },
|
||||
},
|
||||
) => self.check_stability(*attr_span, span, level, *feature, target),
|
||||
Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
|
||||
Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
|
||||
self.check_inline(hir_id, *attr_span, span, kind, target)
|
||||
|
|
@ -288,6 +301,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
&Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => {
|
||||
self.check_rustc_std_internal_symbol(attr_span, span, target)
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => {
|
||||
self.check_coverage(attr_span, span, target)
|
||||
}
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
match attr.path().as_slice() {
|
||||
|
|
@ -297,7 +313,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::diagnostic, sym::on_unimplemented, ..] => {
|
||||
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
|
||||
}
|
||||
[sym::coverage, ..] => self.check_coverage(attr, span, target),
|
||||
[sym::no_sanitize, ..] => {
|
||||
self.check_no_sanitize(attr, span, target)
|
||||
}
|
||||
|
|
@ -492,7 +507,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
attr: &Attribute,
|
||||
item: Option<ItemLike<'_>>,
|
||||
) {
|
||||
if !matches!(target, Target::Impl)
|
||||
if !matches!(target, Target::Impl { .. })
|
||||
|| matches!(
|
||||
item,
|
||||
Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. }))
|
||||
|
|
@ -588,7 +603,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
|
||||
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
|
||||
/// or to an impl block or module.
|
||||
fn check_coverage(&self, attr: &Attribute, target_span: Span, target: Target) {
|
||||
fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) {
|
||||
let mut not_fn_impl_mod = None;
|
||||
let mut no_body = None;
|
||||
|
||||
|
|
@ -596,7 +611,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Target::Fn
|
||||
| Target::Closure
|
||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
|
||||
| Target::Impl
|
||||
| Target::Impl { .. }
|
||||
| Target::Mod => return,
|
||||
|
||||
// These are "functions", but they aren't allowed because they don't
|
||||
|
|
@ -611,7 +626,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
self.dcx().emit_err(errors::CoverageAttributeNotAllowed {
|
||||
attr_span: attr.span(),
|
||||
attr_span,
|
||||
not_fn_impl_mod,
|
||||
no_body,
|
||||
help: (),
|
||||
|
|
@ -985,9 +1000,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
let span = meta.span();
|
||||
if let Some(location) = match target {
|
||||
Target::AssocTy => {
|
||||
let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
|
||||
let containing_item = self.tcx.hir_expect_item(parent_def_id);
|
||||
if Target::from_item(containing_item) == Target::Impl {
|
||||
if let DefKind::Impl { .. } =
|
||||
self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id))
|
||||
{
|
||||
Some("type alias in implementation block")
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1010,7 +1025,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| Target::Arm
|
||||
| Target::ForeignMod
|
||||
| Target::Closure
|
||||
| Target::Impl
|
||||
| Target::Impl { .. }
|
||||
| Target::WherePredicate => Some(target.name()),
|
||||
Target::ExternCrate
|
||||
| Target::Use
|
||||
|
|
@ -1031,7 +1046,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| Target::ForeignFn
|
||||
| Target::ForeignStatic
|
||||
| Target::ForeignTy
|
||||
| Target::GenericParam(..)
|
||||
| Target::GenericParam { .. }
|
||||
| Target::MacroDef
|
||||
| Target::PatField
|
||||
| Target::ExprField => None,
|
||||
|
|
@ -1588,7 +1603,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
let article = match target {
|
||||
Target::ExternCrate
|
||||
| Target::Enum
|
||||
| Target::Impl
|
||||
| Target::Impl { .. }
|
||||
| Target::Expression
|
||||
| Target::Arm
|
||||
| Target::AssocConst
|
||||
|
|
@ -2272,7 +2287,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
match target {
|
||||
// FIXME(staged_api): There's no reason we can't support more targets here. We're just
|
||||
// being conservative to begin with.
|
||||
Target::Fn | Target::Impl => {}
|
||||
Target::Fn | Target::Impl { .. } => {}
|
||||
Target::ExternCrate
|
||||
| Target::Use
|
||||
| Target::Static
|
||||
|
|
@ -2298,7 +2313,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| Target::ForeignFn
|
||||
| Target::ForeignStatic
|
||||
| Target::ForeignTy
|
||||
| Target::GenericParam(_)
|
||||
| Target::GenericParam { .. }
|
||||
| Target::MacroDef
|
||||
| Target::Param
|
||||
| Target::PatField
|
||||
|
|
@ -2318,13 +2333,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_stability_promotable(&self, span: Span, target: Target) {
|
||||
fn check_stability(
|
||||
&self,
|
||||
attr_span: Span,
|
||||
item_span: Span,
|
||||
level: &StabilityLevel,
|
||||
feature: Symbol,
|
||||
target: Target,
|
||||
) {
|
||||
match target {
|
||||
Target::Expression => {
|
||||
self.dcx().emit_err(errors::StabilityPromotable { attr_span: span });
|
||||
self.dcx().emit_err(errors::StabilityPromotable { attr_span });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Stable *language* features shouldn't be used as unstable library features.
|
||||
// (Not doing this for stable library features is checked by tidy.)
|
||||
if level.is_unstable()
|
||||
&& ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
|
||||
{
|
||||
self.tcx
|
||||
.dcx()
|
||||
.emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span });
|
||||
}
|
||||
}
|
||||
|
||||
fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) {
|
||||
|
|
@ -2352,6 +2384,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
errors::Deprecated,
|
||||
);
|
||||
}
|
||||
Target::Impl { of_trait: true }
|
||||
| Target::GenericParam { has_default: false, kind: _ } => {
|
||||
self.tcx.emit_node_span_lint(
|
||||
USELESS_DEPRECATED,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
|
||||
);
|
||||
}
|
||||
Target::AssocConst | Target::Method(..) | Target::AssocTy
|
||||
if matches!(
|
||||
self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)),
|
||||
DefKind::Impl { of_trait: true }
|
||||
) =>
|
||||
{
|
||||
self.tcx.emit_node_span_lint(
|
||||
USELESS_DEPRECATED,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1373,9 +1373,9 @@ pub(crate) struct UnstableAttrForAlreadyStableFeature {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
#[help]
|
||||
pub span: Span,
|
||||
pub attr_span: Span,
|
||||
#[label(passes_item)]
|
||||
pub item_sp: Span,
|
||||
pub item_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
|
|||
ast::ItemKind::Union(..) => Target::Union,
|
||||
ast::ItemKind::Trait(_) => Target::Trait,
|
||||
ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
|
||||
ast::ItemKind::Impl(_) => Target::Impl,
|
||||
ast::ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
|
||||
ast::ItemKind::MacroDef(..) => Target::MacroDef,
|
||||
ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
|
||||
unreachable!("macros should have been expanded")
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
StabilityLevel::Stable { since, .. } => FeatureStability::AcceptedSince(match since {
|
||||
StableSince::Version(v) => Symbol::intern(&v.to_string()),
|
||||
StableSince::Current => sym::env_CFG_RELEASE,
|
||||
StableSince::Err => return None,
|
||||
StableSince::Err(_) => return None,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -144,10 +144,10 @@ where
|
|||
#[macro_export]
|
||||
macro_rules! run {
|
||||
($args:expr, $callback_fn:ident) => {
|
||||
run_driver!($args, || $callback_fn())
|
||||
$crate::run_driver!($args, || $callback_fn())
|
||||
};
|
||||
($args:expr, $callback:expr) => {
|
||||
run_driver!($args, $callback)
|
||||
$crate::run_driver!($args, $callback)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -158,10 +158,10 @@ macro_rules! run {
|
|||
#[macro_export]
|
||||
macro_rules! run_with_tcx {
|
||||
($args:expr, $callback_fn:ident) => {
|
||||
run_driver!($args, |tcx| $callback_fn(tcx), with_tcx)
|
||||
$crate::run_driver!($args, |tcx| $callback_fn(tcx), with_tcx)
|
||||
};
|
||||
($args:expr, $callback:expr) => {
|
||||
run_driver!($args, $callback, with_tcx)
|
||||
$crate::run_driver!($args, $callback, with_tcx)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -191,11 +191,11 @@ macro_rules! run_driver {
|
|||
use rustc_public::CompilerError;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
pub struct StableMir<B = (), C = (), F = fn($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C>>
|
||||
pub struct StableMir<B = (), C = (), F = fn($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C>>
|
||||
where
|
||||
B: Send,
|
||||
C: Send,
|
||||
F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
{
|
||||
callback: Option<F>,
|
||||
result: Option<ControlFlow<B, C>>,
|
||||
|
|
@ -205,7 +205,7 @@ macro_rules! run_driver {
|
|||
where
|
||||
B: Send,
|
||||
C: Send,
|
||||
F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
{
|
||||
/// Creates a new `StableMir` instance, with given test_function and arguments.
|
||||
pub fn new(callback: F) -> Self {
|
||||
|
|
@ -240,7 +240,7 @@ macro_rules! run_driver {
|
|||
where
|
||||
B: Send,
|
||||
C: Send,
|
||||
F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
|
||||
{
|
||||
/// Called after analysis. Return value instructs the compiler whether to
|
||||
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
|
||||
|
|
@ -251,7 +251,7 @@ macro_rules! run_driver {
|
|||
) -> Compilation {
|
||||
if let Some(callback) = self.callback.take() {
|
||||
rustc_internal::run(tcx, || {
|
||||
self.result = Some(callback($(optional!($with_tcx tcx))?));
|
||||
self.result = Some(callback($($crate::optional!($with_tcx tcx))?));
|
||||
})
|
||||
.unwrap();
|
||||
if self.result.as_ref().is_some_and(|val| val.is_continue()) {
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ns: Namespace,
|
||||
binding: NameBinding<'ra>,
|
||||
) {
|
||||
let key = self.new_disambiguated_key(ident, ns);
|
||||
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
|
||||
if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
|
||||
self.report_conflict(parent, ident, ns, old_binding, binding);
|
||||
}
|
||||
}
|
||||
|
|
@ -442,16 +441,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||
|
||||
self.r.indeterminate_imports.push(import);
|
||||
match import.kind {
|
||||
// Don't add unresolved underscore imports to modules
|
||||
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
|
||||
ImportKind::Single { target, type_ns_only, .. } => {
|
||||
self.r.per_ns(|this, ns| {
|
||||
if !type_ns_only || ns == TypeNS {
|
||||
let key = BindingKey::new(target, ns);
|
||||
let mut resolution = this.resolution(current_module, key).borrow_mut();
|
||||
resolution.single_imports.insert(import);
|
||||
}
|
||||
});
|
||||
// Don't add underscore imports to `single_imports`
|
||||
// because they cannot define any usable names.
|
||||
if target.name != kw::Underscore {
|
||||
self.r.per_ns(|this, ns| {
|
||||
if !type_ns_only || ns == TypeNS {
|
||||
let key = BindingKey::new(target, ns);
|
||||
let mut resolution = this.resolution(current_module, key).borrow_mut();
|
||||
resolution.single_imports.insert(import);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
||||
// which are not relevant to import resolution.
|
||||
|
|
@ -1405,9 +1406,12 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||
let parent = self.parent_scope.module;
|
||||
let expansion = self.parent_scope.expansion;
|
||||
self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
|
||||
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
|
||||
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
|
||||
&& ident.name != kw::Underscore
|
||||
{
|
||||
// Don't add underscore names, they cannot be looked up anyway.
|
||||
let impl_def_id = self.r.tcx.local_parent(local_def_id);
|
||||
let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
|
||||
let key = BindingKey::new(ident, ns);
|
||||
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym};
|
|||
use smallvec::SmallVec;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::Namespace::*;
|
||||
use crate::Namespace::{self, *};
|
||||
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
|
||||
use crate::errors::{
|
||||
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
||||
|
|
@ -338,13 +338,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
pub(crate) fn try_define(
|
||||
&mut self,
|
||||
module: Module<'ra>,
|
||||
key: BindingKey,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
binding: NameBinding<'ra>,
|
||||
warn_ambiguity: bool,
|
||||
) -> Result<(), NameBinding<'ra>> {
|
||||
let res = binding.res();
|
||||
self.check_reserved_macro_name(key.ident, res);
|
||||
self.check_reserved_macro_name(ident, res);
|
||||
self.set_binding_parent_module(binding, module);
|
||||
// Even if underscore names cannot be looked up, we still need to add them to modules,
|
||||
// because they can be fetched by glob imports from those modules, and bring traits
|
||||
// into scope both directly and through glob imports.
|
||||
let key = BindingKey::new_disambiguated(ident, ns, || {
|
||||
(module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
|
||||
});
|
||||
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
|
||||
if let Some(old_binding) = resolution.best_binding() {
|
||||
if res == Res::Err && old_binding.res() != Res::Err {
|
||||
|
|
@ -383,7 +390,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
(old_glob @ true, false) | (old_glob @ false, true) => {
|
||||
let (glob_binding, non_glob_binding) =
|
||||
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
||||
if key.ns == MacroNS
|
||||
if ns == MacroNS
|
||||
&& non_glob_binding.expansion != LocalExpnId::ROOT
|
||||
&& glob_binding.res() != non_glob_binding.res()
|
||||
{
|
||||
|
|
@ -489,10 +496,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
};
|
||||
if self.is_accessible_from(binding.vis, scope) {
|
||||
let imported_binding = self.import(binding, *import);
|
||||
let key = BindingKey { ident, ..key };
|
||||
let _ = self.try_define(
|
||||
import.parent_scope.module,
|
||||
key,
|
||||
ident,
|
||||
key.ns,
|
||||
imported_binding,
|
||||
warn_ambiguity,
|
||||
);
|
||||
|
|
@ -514,11 +521,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
let dummy_binding = self.dummy_binding;
|
||||
let dummy_binding = self.import(dummy_binding, import);
|
||||
self.per_ns(|this, ns| {
|
||||
let key = BindingKey::new(target, ns);
|
||||
let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
|
||||
this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
|
||||
resolution.single_imports.swap_remove(&import);
|
||||
})
|
||||
let module = import.parent_scope.module;
|
||||
let _ = this.try_define(module, target, ns, dummy_binding, false);
|
||||
// Don't remove underscores from `single_imports`, they were never added.
|
||||
if target.name != kw::Underscore {
|
||||
let key = BindingKey::new(target, ns);
|
||||
this.update_resolution(module, key, false, |_, resolution| {
|
||||
resolution.single_imports.swap_remove(&import);
|
||||
})
|
||||
}
|
||||
});
|
||||
self.record_use(target, dummy_binding, Used::Other);
|
||||
} else if import.imported_module.get().is_none() {
|
||||
|
|
@ -895,7 +906,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
PendingBinding::Ready(Some(imported_binding))
|
||||
}
|
||||
Err(Determinacy::Determined) => {
|
||||
// Don't update the resolution for underscores, because it was never added.
|
||||
// Don't remove underscores from `single_imports`, they were never added.
|
||||
if target.name != kw::Underscore {
|
||||
let key = BindingKey::new(target, ns);
|
||||
this.update_resolution(parent, key, false, |_, resolution| {
|
||||
|
|
@ -1510,7 +1521,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
.is_some_and(|binding| binding.warn_ambiguity_recursive());
|
||||
let _ = self.try_define(
|
||||
import.parent_scope.module,
|
||||
key,
|
||||
key.ident,
|
||||
key.ns,
|
||||
imported_binding,
|
||||
warn_ambiguity,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2899,9 +2899,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
|
||||
if param.ident.name == kw::UnderscoreLifetime {
|
||||
// To avoid emitting two similar errors,
|
||||
// we need to check if the span is a raw underscore lifetime, see issue #143152
|
||||
let is_raw_underscore_lifetime = self
|
||||
.r
|
||||
.tcx
|
||||
.sess
|
||||
.psess
|
||||
.raw_identifier_spans
|
||||
.iter()
|
||||
.any(|span| span == param.span());
|
||||
|
||||
self.r
|
||||
.dcx()
|
||||
.emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
|
||||
.create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
|
||||
.emit_unless(is_raw_underscore_lifetime);
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -532,15 +532,26 @@ struct BindingKey {
|
|||
/// identifier.
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
/// 0 if ident is not `_`, otherwise a value that's unique to the specific
|
||||
/// `_` in the expanded AST that introduced this binding.
|
||||
/// When we add an underscore binding (with ident `_`) to some module, this field has
|
||||
/// a non-zero value that uniquely identifies this binding in that module.
|
||||
/// For non-underscore bindings this field is zero.
|
||||
/// When a key is constructed for name lookup (as opposed to name definition), this field is
|
||||
/// also zero, even for underscore names, so for underscores the lookup will never succeed.
|
||||
disambiguator: u32,
|
||||
}
|
||||
|
||||
impl BindingKey {
|
||||
fn new(ident: Ident, ns: Namespace) -> Self {
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
BindingKey { ident, ns, disambiguator: 0 }
|
||||
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 }
|
||||
}
|
||||
|
||||
fn new_disambiguated(
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
disambiguator: impl FnOnce() -> u32,
|
||||
) -> BindingKey {
|
||||
let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
|
||||
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1087,8 +1098,6 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
|
||||
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
|
||||
|
||||
underscore_disambiguator: u32,
|
||||
|
||||
/// Maps glob imports to the names of items actually imported.
|
||||
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
|
||||
glob_error: Option<ErrorGuaranteed>,
|
||||
|
|
@ -1501,7 +1510,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
extern_crate_map: Default::default(),
|
||||
module_children: Default::default(),
|
||||
trait_map: NodeMap::default(),
|
||||
underscore_disambiguator: 0,
|
||||
empty_module,
|
||||
local_module_map,
|
||||
extern_module_map: Default::default(),
|
||||
|
|
@ -1887,17 +1895,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
import_ids
|
||||
}
|
||||
|
||||
fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
let disambiguator = if ident.name == kw::Underscore {
|
||||
self.underscore_disambiguator += 1;
|
||||
self.underscore_disambiguator
|
||||
} else {
|
||||
0
|
||||
};
|
||||
BindingKey { ident, ns, disambiguator }
|
||||
}
|
||||
|
||||
fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
|
||||
if module.populate_on_access.get() {
|
||||
module.populate_on_access.set(false);
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
target_trait.for_each_child(self, |this, ident, ns, _binding| {
|
||||
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
|
||||
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
|
||||
&& overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
|
||||
&& overriding_keys.contains(&BindingKey::new(ident, ns))
|
||||
{
|
||||
// The name is overridden, do not produce it from the glob delegation.
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1708,6 +1708,11 @@ impl RustcOptGroup {
|
|||
OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
|
||||
};
|
||||
}
|
||||
|
||||
/// This is for diagnostics-only.
|
||||
pub fn long_name(&self) -> &str {
|
||||
self.long_name
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_opt(
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue