Auto merge of #133377 - jieyouxu:rollup-n536hzq, r=jieyouxu

Rollup of 6 pull requests

Successful merges:

 - #127483 (Allow disabling ASan instrumentation for globals)
 - #131505 (use `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)` as a `TMPDIR` fallback on Darwin)
 - #132949 (Add specific diagnostic for using macro_rules macro as attribute/derive)
 - #133286 (Re-delay a resolve `bug` related to `Self`-ctor in patterns)
 - #133332 (Mark `<[T; N]>::as_mut_slice` with the `const` specifier.)
 - #133366 (Remove unnecessary bool from `ExpectedFound::new`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-11-23 15:19:32 +00:00
commit 826b673412
37 changed files with 438 additions and 141 deletions

View File

@ -172,3 +172,12 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
Visibility::Protected => llvm::Visibility::Protected,
}
}
pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) {
if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) {
unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) };
}
if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) {
unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) };
}
}

View File

@ -470,6 +470,8 @@ impl<'ll> CodegenCx<'ll, '_> {
base::set_link_section(g, attrs);
}
base::set_variable_sanitizer_attrs(g, attrs);
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// `USED` and `USED_LINKER` can't be used together.
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));

View File

@ -2460,4 +2460,7 @@ unsafe extern "C" {
pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
pub fn LLVMRustSetNoSanitizeAddress(Global: &Value);
pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
}

View File

@ -729,7 +729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let can_coerce = self.may_coerce(arg_ty, coerced_ty);
if !can_coerce {
return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
ty::error::ExpectedFound::new(coerced_ty, arg_ty),
)));
}
@ -758,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
expected_ty
};
TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty)
TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
};
// The algorithm here is inspired by levenshtein distance and longest common subsequence.

View File

@ -308,17 +308,14 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
}
}
}
impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Regions(ExpectedFound::new(true, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::Regions(ExpectedFound::new(a, b)) }
}
}
@ -326,7 +323,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
}
}
}
@ -337,13 +334,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
cause: cause.clone(),
values: match (a.unpack(), b.unpack()) {
(GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
ValuePairs::Regions(ExpectedFound::new(true, a, b))
ValuePairs::Regions(ExpectedFound::new(a, b))
}
(GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
}
(GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
}
_ => bug!("relating different kinds: {a:?} {b:?}"),
},
@ -353,19 +350,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(true, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::Terms(ExpectedFound::new(a, b)) }
}
}
impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::TraitRefs(ExpectedFound::new(true, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
}
}
@ -373,17 +364,14 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Aliases(ExpectedFound::new(true, a.into(), b.into())),
values: ValuePairs::Aliases(ExpectedFound::new(a.into(), b.into())),
}
}
}
impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Aliases(ExpectedFound::new(true, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::Aliases(ExpectedFound::new(a, b)) }
}
}
@ -392,7 +380,6 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::PolySigs(ExpectedFound::new(
true,
ty::Binder::dummy(a),
ty::Binder::dummy(b),
)),
@ -402,10 +389,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::PolySigs(ExpectedFound::new(true, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new(a, b)) }
}
}
@ -413,7 +397,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(true, a, b)),
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a, b)),
}
}
}
@ -422,7 +406,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::ExistentialProjection(ExpectedFound::new(true, a, b)),
values: ValuePairs::ExistentialProjection(ExpectedFound::new(a, b)),
}
}
}

View File

@ -1478,39 +1478,29 @@ impl<'tcx> TypeTrace<'tcx> {
self.cause.span
}
pub fn types(
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Ty<'tcx>,
b: Ty<'tcx>,
) -> TypeTrace<'tcx> {
pub fn types(cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
}
}
pub fn trait_refs(
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: ty::TraitRef<'tcx>,
b: ty::TraitRef<'tcx>,
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
}
TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
}
pub fn consts(
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: ty::Const<'tcx>,
b: ty::Const<'tcx>,
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
}
}
}

View File

@ -177,7 +177,7 @@ impl<'tcx> InferCtxt<'tcx> {
res
} else {
let (a, b) = self.resolve_vars_if_possible((a, b));
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
}
}

View File

@ -2051,6 +2051,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
return llvm::compression::zstd::isAvailable();
}
extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) {
GlobalValue &GV = *unwrap<GlobalValue>(Global);
GlobalValue::SanitizerMetadata MD;
if (GV.hasSanitizerMetadata())
MD = GV.getSanitizerMetadata();
MD.NoAddress = true;
MD.IsDynInit = false;
GV.setSanitizerMetadata(MD);
}
extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
GlobalValue &GV = *unwrap<GlobalValue>(Global);
GlobalValue::SanitizerMetadata MD;
if (GV.hasSanitizerMetadata())
MD = GV.getSanitizerMetadata();
MD.NoHWAddress = true;
GV.setSanitizerMetadata(MD);
}
// Operations on composite constants.
// These are clones of LLVM api functions that will become available in future
// releases. They can be removed once Rust's minimum supported LLVM version

View File

@ -92,7 +92,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
b_v.dedup();
if a_v.len() != b_v.len() {
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b)));
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
}
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
@ -112,7 +112,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
ty::ExistentialPredicate::AutoTrait(a),
ty::ExistentialPredicate::AutoTrait(b),
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))),
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
}
});
tcx.mk_poly_existential_predicates_from_iter(v)

View File

@ -558,6 +558,10 @@ passes_no_mangle_foreign =
passes_no_patterns =
patterns not allowed in naked function parameters
passes_no_sanitize =
`#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
.label = not {$accepted_kind}
passes_non_exported_macro_invalid_attrs =
attribute should be applied to function or closure
.label = not a function or closure

View File

@ -126,9 +126,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
[sym::coverage, ..] => self.check_coverage(attr, span, target),
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
[sym::no_sanitize, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
[sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target),
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
[sym::target_feature, ..] => {
@ -450,6 +448,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
let sym = item.name_or_empty();
match sym {
sym::address | sym::hwaddress => {
let is_valid =
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
if !is_valid {
self.dcx().emit_err(errors::NoSanitize {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function or static",
attr_str: sym.as_str(),
});
}
}
_ => {
let is_valid = matches!(target, Target::Fn | Target::Method(..));
if !is_valid {
self.dcx().emit_err(errors::NoSanitize {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function",
attr_str: sym.as_str(),
});
}
}
}
}
}
}
fn check_generic_attr(
&self,
hir_id: HirId,

View File

@ -1846,3 +1846,14 @@ pub(crate) struct AttrCrateLevelOnlySugg {
#[primary_span]
pub attr: Span,
}
#[derive(Diagnostic)]
#[diag(passes_no_sanitize)]
pub(crate) struct NoSanitize<'a> {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
pub accepted_kind: &'a str,
pub attr_str: &'a str,
}

View File

@ -257,8 +257,14 @@ resolve_lowercase_self =
attempt to use a non-constant value in a constant
.suggestion = try using `Self`
resolve_macro_cannot_use_as_attr =
`{$ident}` exists, but a declarative macro cannot be used as an attribute macro
resolve_macro_cannot_use_as_derive =
`{$ident}` exists, but a declarative macro cannot be used as a derive macro
resolve_macro_defined_later =
a macro with the same name exists, but it appears later at here
a macro with the same name exists, but it appears later
resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments =
macro-expanded `extern crate` items cannot shadow names passed with `--extern`

View File

@ -35,7 +35,8 @@ use tracing::debug;
use crate::errors::{
self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName,
ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
MaybeMissingMacroRulesName,
};
use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib};
@ -1473,8 +1474,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let scope = self.local_macro_def_scopes[&def_id];
let parent_nearest = parent_scope.module.nearest_parent_mod();
if Some(parent_nearest) == scope.opt_def_id() {
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
match macro_kind {
MacroKind::Bang => {
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
}
MacroKind::Attr => {
err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
}
MacroKind::Derive => {
err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
}
}
return;
}
}

View File

@ -665,6 +665,22 @@ pub(crate) struct MacroSuggMovePosition {
pub(crate) ident: Ident,
}
#[derive(Subdiagnostic)]
pub(crate) enum MacroRulesNot {
#[label(resolve_macro_cannot_use_as_attr)]
Attr {
#[primary_span]
span: Span,
ident: Ident,
},
#[label(resolve_macro_cannot_use_as_derive)]
Derive {
#[primary_span]
span: Span,
ident: Ident,
},
}
#[derive(Subdiagnostic)]
#[note(resolve_missing_macro_rules_name)]
pub(crate) struct MaybeMissingMacroRulesName {

View File

@ -3940,12 +3940,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
Res::SelfCtor(_) => {
// We resolve `Self` in pattern position as an ident sometimes during recovery,
// so delay a bug instead of ICEing. (Note: is this no longer true? We now ICE. If
// this triggers, please convert to a delayed bug and add a test.)
self.r.dcx().span_bug(
// so delay a bug instead of ICEing.
self.r.dcx().span_delayed_bug(
ident.span,
"unexpected `SelfCtor` in pattern, expected identifier"
);
None
}
_ => span_bug!(
ident.span,

View File

@ -152,7 +152,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(
TypeTrace::types(cause, true, expected, actual),
TypeTrace::types(cause, expected, actual),
param_env,
err,
)
@ -167,7 +167,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(
TypeTrace::consts(cause, true, expected, actual),
TypeTrace::consts(cause, expected, actual),
param_env,
err,
)

View File

@ -725,7 +725,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&obligation.cause,
None,
None,
TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)),
TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),
false,
);
diag
@ -1449,7 +1449,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
secondary_span,
values.map(|(_, normalized_ty, expected_ty)| {
obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new(
true,
expected_ty,
normalized_ty,
)))
@ -2755,7 +2754,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
(obligation.cause.clone(), terr)
};
self.report_and_explain_type_error(
TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
TypeTrace::trait_refs(&cause, expected_trait_ref, found_trait_ref),
obligation.param_env,
terr,
)
@ -2846,7 +2845,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
{
return Ok(self.report_and_explain_type_error(
TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref),
TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
obligation.param_env,
ty::error::TypeError::Mismatch,
));

View File

@ -264,14 +264,14 @@ fn fulfillment_error_for_no_solution<'tcx>(
let (a, b) = infcx.enter_forall_and_leak_universe(
obligation.predicate.kind().rebind((pred.a, pred.b)),
);
let expected_found = ExpectedFound::new(true, a, b);
let expected_found = ExpectedFound::new(a, b);
FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
}
ty::PredicateKind::Coerce(pred) => {
let (a, b) = infcx.enter_forall_and_leak_universe(
obligation.predicate.kind().rebind((pred.a, pred.b)),
);
let expected_found = ExpectedFound::new(false, a, b);
let expected_found = ExpectedFound::new(b, a);
FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
}
ty::PredicateKind::Clause(_)

View File

@ -557,8 +557,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ProcessResult::Changed(mk_pending(ok.obligations))
}
Ok(Err(err)) => {
let expected_found =
ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b);
let expected_found = if subtype.a_is_expected {
ExpectedFound::new(subtype.a, subtype.b)
} else {
ExpectedFound::new(subtype.b, subtype.a)
};
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
}
}
@ -578,7 +581,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
Ok(Err(err)) => {
let expected_found = ExpectedFound::new(false, coerce.a, coerce.b);
let expected_found = ExpectedFound::new(coerce.b, coerce.a);
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
}
}
@ -703,7 +706,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
Err(err) => {
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
ExpectedFound::new(true, c1, c2),
ExpectedFound::new(c1, c2),
err,
))
}
@ -727,7 +730,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ProcessResult::Unchanged
} else {
// Two different constants using generic parameters ~> error.
let expected_found = ExpectedFound::new(true, c1, c2);
let expected_found = ExpectedFound::new(c1, c2);
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
expected_found,
TypeError::ConstMismatch(expected_found),

View File

@ -70,7 +70,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
) => Ok(a),
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
}
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)),
@ -95,7 +95,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
}
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b)));
return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b)));
}
_ => {}

View File

@ -12,12 +12,8 @@ pub struct ExpectedFound<T> {
}
impl<T> ExpectedFound<T> {
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
if a_is_expected {
ExpectedFound { expected: a, found: b }
} else {
ExpectedFound { expected: b, found: a }
}
pub fn new(expected: T, found: T) -> Self {
ExpectedFound { expected, found }
}
}

View File

@ -171,16 +171,16 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
return Err(TypeError::VariadicMismatch({
let a = a.c_variadic;
let b = b.c_variadic;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}));
}
if a.safety != b.safety {
return Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a.safety, b.safety)));
return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety, b.safety)));
}
if a.abi != b.abi {
return Err(TypeError::AbiMismatch(ExpectedFound::new(true, a.abi, b.abi)));
return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi, b.abi)));
};
let a_inputs = a.inputs();
@ -233,7 +233,7 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}))
} else {
let args = match a.kind(relation.cx()) {
@ -274,7 +274,7 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}))
} else {
let args = match a.kind(relation.cx()) {
@ -309,7 +309,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}))
} else {
let term = relation.relate_with_variance(
@ -340,7 +340,7 @@ impl<I: Interner> Relate<I> for ty::TraitRef<I> {
Err(TypeError::Traits({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
@ -360,7 +360,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
Err(TypeError::Traits({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
ExpectedFound::new(a, b)
}))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
@ -508,9 +508,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
let sz_b = sz_b.try_to_target_usize(cx);
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(ExpectedFound::new(true, sz_a_val, sz_b_val)),
),
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
Err(TypeError::FixedArraySize(ExpectedFound::new(sz_a_val, sz_b_val)))
}
_ => Err(err),
}
}
@ -529,9 +529,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)),
)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(ExpectedFound::new(true, as_.len(), bs.len())))
Err(TypeError::TupleSize(ExpectedFound::new(as_.len(), bs.len())))
} else {
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
}
}
@ -558,7 +558,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
Ok(Ty::new_pat(cx, ty, pat))
}
_ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))),
_ => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
}
}
@ -637,7 +637,7 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
}
_ => false,
};
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))) }
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))) }
}
impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
@ -658,9 +658,7 @@ impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
) -> RelateResult<I, ty::TraitPredicate<I>> {
let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
if a.polarity != b.polarity {
return Err(TypeError::PolarityMismatch(ExpectedFound::new(
true, a.polarity, b.polarity,
)));
return Err(TypeError::PolarityMismatch(ExpectedFound::new(a.polarity, b.polarity)));
}
Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
}

View File

@ -123,9 +123,7 @@ where
}
// All other cases of inference are errors
(ty::Infer(_), _) | (_, ty::Infer(_)) => {
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
}
(ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
(ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
assert!(!infcx.next_trait_solver());

View File

@ -579,7 +579,8 @@ impl<T, const N: usize> [T; N] {
/// Returns a mutable slice containing the entire array. Equivalent to
/// `&mut s[..]`.
#[stable(feature = "array_as_slice", since = "1.57.0")]
pub fn as_mut_slice(&mut self) -> &mut [T] {
#[rustc_const_unstable(feature = "const_array_as_mut_slice", issue = "133333")]
pub const fn as_mut_slice(&mut self) -> &mut [T] {
self
}

View File

@ -653,19 +653,28 @@ pub fn home_dir() -> Option<PathBuf> {
/// may result in "insecure temporary file" security vulnerabilities. Consider
/// using a crate that securely creates temporary files or directories.
///
/// Note that the returned value may be a symbolic link, not a directory.
///
/// # Platform-specific behavior
///
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. On Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
/// set, otherwise the value is OS-specific:
/// - On Android, there is no global temporary folder (it is usually allocated
/// per-app), it returns `/data/local/tmp`.
/// - On Darwin-based OSes (macOS, iOS, etc) it returns the directory provided
/// by `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)`, as recommended by [Apple's
/// security guidelines][appledoc].
/// - On all other unix-based OSes, it returns `/tmp`.
///
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
/// [`GetTempPath`][GetTempPath], which this function uses internally.
///
/// Note that, this [may change in the future][changes].
///
/// [changes]: io#platform-specific-behavior
/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
/// [appledoc]: https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
///
/// ```no_run
/// use std::env;

View File

@ -698,12 +698,82 @@ pub fn page_size() -> usize {
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
}
// Returns the value for [`confstr(key, ...)`][posix_confstr]. Currently only
// used on Darwin, but should work on any unix (in case we need to get
// `_CS_PATH` or `_CS_V[67]_ENV` in the future).
//
// [posix_confstr]:
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html
//
// FIXME: Support `confstr` in Miri.
#[cfg(all(target_vendor = "apple", not(miri)))]
fn confstr(key: c_int, size_hint: Option<usize>) -> io::Result<OsString> {
let mut buf: Vec<u8> = Vec::with_capacity(0);
let mut bytes_needed_including_nul = size_hint
.unwrap_or_else(|| {
// Treat "None" as "do an extra call to get the length". In theory
// we could move this into the loop below, but it's hard to do given
// that it isn't 100% clear if it's legal to pass 0 for `len` when
// the buffer isn't null.
unsafe { libc::confstr(key, core::ptr::null_mut(), 0) }
})
.max(1);
// If the value returned by `confstr` is greater than the len passed into
// it, then the value was truncated, meaning we need to retry. Note that
// while `confstr` results don't seem to change for a process, it's unclear
// if this is guaranteed anywhere, so looping does seem required.
while bytes_needed_including_nul > buf.capacity() {
// We write into the spare capacity of `buf`. This lets us avoid
// changing buf's `len`, which both simplifies `reserve` computation,
// allows working with `Vec<u8>` instead of `Vec<MaybeUninit<u8>>`, and
// may avoid a copy, since the Vec knows that none of the bytes are needed
// when reallocating (well, in theory anyway).
buf.reserve(bytes_needed_including_nul);
// `confstr` returns
// - 0 in the case of errors: we break and return an error.
// - The number of bytes written, iff the provided buffer is enough to
// hold the entire value: we break and return the data in `buf`.
// - Otherwise, the number of bytes needed (including nul): we go
// through the loop again.
bytes_needed_including_nul =
unsafe { libc::confstr(key, buf.as_mut_ptr().cast::<c_char>(), buf.capacity()) };
}
// `confstr` returns 0 in the case of an error.
if bytes_needed_including_nul == 0 {
return Err(io::Error::last_os_error());
}
// Safety: `confstr(..., buf.as_mut_ptr(), buf.capacity())` returned a
// non-zero value, meaning `bytes_needed_including_nul` bytes were
// initialized.
unsafe {
buf.set_len(bytes_needed_including_nul);
// Remove the NUL-terminator.
let last_byte = buf.pop();
// ... and smoke-check that it *was* a NUL-terminator.
assert_eq!(last_byte, Some(0), "`confstr` provided a string which wasn't nul-terminated");
};
Ok(OsString::from_vec(buf))
}
#[cfg(all(target_vendor = "apple", not(miri)))]
fn darwin_temp_dir() -> PathBuf {
confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| {
// It failed for whatever reason (there are several possible reasons),
// so return the global one.
PathBuf::from("/tmp")
})
}
pub fn temp_dir() -> PathBuf {
crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
if cfg!(target_os = "android") {
PathBuf::from("/data/local/tmp")
} else {
PathBuf::from("/tmp")
cfg_if::cfg_if! {
if #[cfg(all(target_vendor = "apple", not(miri)))] {
darwin_temp_dir()
} else if #[cfg(target_os = "android")] {
PathBuf::from("/data/local/tmp")
} else {
PathBuf::from("/tmp")
}
}
})
}

View File

@ -21,3 +21,28 @@ fn test_parse_glibc_version() {
assert_eq!(parsed, super::parse_glibc_version(version_str));
}
}
// Smoke check `confstr`, do it for several hint values, to ensure our resizing
// logic is correct.
#[test]
#[cfg(all(target_vendor = "apple", not(miri)))]
fn test_confstr() {
for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] {
let value_nohint = super::confstr(key, None).unwrap_or_else(|e| {
panic!("confstr({key}, None) failed: {e:?}");
});
let end = (value_nohint.len() + 1) * 2;
for hint in 0..end {
assert_eq!(
super::confstr(key, Some(hint)).as_deref().ok(),
Some(&*value_nohint),
"confstr({key}, Some({hint})) failed",
);
}
}
// Smoke check that we don't loop forever or something if the input was not valid.
for hint in [None, Some(0), Some(1)] {
let hopefully_invalid = 123456789_i32;
assert!(super::confstr(hopefully_invalid, hint).is_err());
}
}

View File

@ -7,6 +7,16 @@
#![crate_type = "lib"]
#![feature(no_sanitize)]
// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address
// CHECK-NOT: @__asan_global_UNSANITIZED
#[no_mangle]
#[no_sanitize(address)]
pub static UNSANITIZED: u32 = 0;
// CHECK: @__asan_global_SANITIZED
#[no_mangle]
pub static SANITIZED: u32 = 0;
// CHECK-LABEL: ; no_sanitize::unsanitized
// CHECK-NEXT: ; Function Attrs:
// CHECK-NOT: sanitize_address

View File

@ -4,31 +4,37 @@
#![allow(dead_code)]
fn invalid() {
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
{
1
};
}
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
type InvalidTy = ();
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
mod invalid_module {}
fn main() {
let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
(|| 1);
}
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
struct F;
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
impl F {
#[no_sanitize(memory)]
fn valid(&self) {}
}
#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
static INVALID : i32 = 0;
#[no_sanitize(memory)]
fn valid() {}
#[no_sanitize(address)]
static VALID : i32 = 0;

View File

@ -1,55 +1,63 @@
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:7:5
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:7:19
|
LL | #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | / {
LL | | 1
LL | | };
| |_____- not a function definition
| |_____- not a function
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:13:1
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:13:15
|
LL | #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | type InvalidTy = ();
| -------------------- not a function definition
| -------------------- not a function
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:16:1
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:16:15
|
LL | #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | mod invalid_module {}
| --------------------- not a function definition
| --------------------- not a function
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:20:13
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:20:27
|
LL | let _ = #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | (|| 1);
| ------ not a function definition
| ------ not a function
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:24:1
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:24:15
|
LL | #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | struct F;
| --------- not a function definition
| --------- not a function
error: attribute should be applied to a function definition
--> $DIR/no-sanitize.rs:27:1
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:27:15
|
LL | #[no_sanitize(memory)]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^
LL | / impl F {
LL | | #[no_sanitize(memory)]
LL | | fn valid(&self) {}
LL | | }
| |_- not a function definition
| |_- not a function
error: aborting due to 6 previous errors
error: `#[no_sanitize(memory)]` should be applied to a function
--> $DIR/no-sanitize.rs:33:24
|
LL | #[no_sanitize(address, memory)]
| ^^^^^^
LL | static INVALID : i32 = 0;
| ------------------------- not a function
error: aborting due to 7 previous errors

View File

@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope
LL | something_later!();
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
note: a macro with the same name exists, but it appears later at here
note: a macro with the same name exists, but it appears later
--> $DIR/defined-later-issue-121061-2.rs:6:18
|
LL | macro_rules! something_later {

View File

@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope
LL | something_later!();
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
note: a macro with the same name exists, but it appears later at here
note: a macro with the same name exists, but it appears later
--> $DIR/defined-later-issue-121061.rs:5:14
|
LL | macro_rules! something_later {

View File

@ -0,0 +1,9 @@
#![crate_type = "lib"]
macro_rules! sample { () => {} }
#[sample] //~ ERROR cannot find attribute `sample` in this scope
#[derive(sample)] //~ ERROR cannot find derive macro `sample` in this scope
//~| ERROR cannot find derive macro `sample` in this scope
//~| ERROR cannot find derive macro `sample` in this scope
pub struct S {}

View File

@ -0,0 +1,42 @@
error: cannot find derive macro `sample` in this scope
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
LL | macro_rules! sample { () => {} }
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
...
LL | #[derive(sample)]
| ^^^^^^
error: cannot find attribute `sample` in this scope
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3
|
LL | macro_rules! sample { () => {} }
| ------ `sample` exists, but a declarative macro cannot be used as an attribute macro
LL |
LL | #[sample]
| ^^^^^^
error: cannot find derive macro `sample` in this scope
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
LL | macro_rules! sample { () => {} }
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
...
LL | #[derive(sample)]
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: cannot find derive macro `sample` in this scope
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
LL | macro_rules! sample { () => {} }
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
...
LL | #[derive(sample)]
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors

View File

@ -0,0 +1,21 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/133272>, where a `ref Self` ctor
//! makes it possible to hit a `delayed_bug` that was converted into a `span_bug` in
//! <https://github.com/rust-lang/rust/pull/121208>, and hitting this reveals that we did not have
//! test coverage for this specific code pattern (heh) previously.
//!
//! # References
//!
//! - ICE bug report: <https://github.com/rust-lang/rust/issues/133272>.
//! - Previous PR to change `delayed_bug` -> `span_bug`:
//! <https://github.com/rust-lang/rust/pull/121208>
#![crate_type = "lib"]
struct Foo;
impl Foo {
fn fun() {
let S { ref Self } = todo!();
//~^ ERROR expected identifier, found keyword `Self`
//~| ERROR cannot find struct, variant or union type `S` in this scope
}
}

View File

@ -0,0 +1,15 @@
error: expected identifier, found keyword `Self`
--> $DIR/self-ctor-133272.rs:17:21
|
LL | let S { ref Self } = todo!();
| ^^^^ expected identifier, found keyword
error[E0422]: cannot find struct, variant or union type `S` in this scope
--> $DIR/self-ctor-133272.rs:17:13
|
LL | let S { ref Self } = todo!();
| ^ not found in this scope
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0422`.